PHP 程式使用資料庫 (5) Table

要用 Azure Table Storage 需要先建立一個 Azure Storage Account, 詳細步驟可以參考這一篇

Azure table storage 的儲存格式比較像表格。一個table裡面可以有很多entities, 而且不同entities裡面可以有不同的格式內容,也就是說雖然都存在table裡面但是存的資料可以很不一樣。Entity是由很多組properties(名稱-值)組成,這些properties的內容,包括他們所存的資料名稱都可以自己定義,也就是不同entity裡面存的東西可以很不一樣。

table

 

所以,要用table首先需要建立一個table, 建立完之後再建立entity然後把它放到table裡面去。

建立table:

下面這個範例會教你怎麼建立table. 基本上,用ServicesBuilder裡面的createTableService函式和連接你的儲存體(storage)的連接資料建立一個連接你的儲存體的table服務TableRestProxy物件。這個物件讓你使用createTable函式建立一個自己命名的table.

require_once 'vendor\autoload.php';

use WindowsAzure\Common\ServicesBuilder;
use WindowsAzure\Common\ServiceException;

// Create table REST proxy.
$tableRestProxy = ServicesBuilder::getInstance()->createTableService($connectionString);

try {
    // Create table.
    $tableRestProxy->createTable("mytable");
}
catch(ServiceException $e){
    $code = $e->getCode();
    $error_message = $e->getMessage();
    // Handle exception based on error codes and messages.
    // Error codes and messages can be found here: 
    // http://msdn.microsoft.com/zh-tw/library/windowsazure/dd179438.aspx
}

建立並加入entity:

建立完 table 後就需要加入儲存資料的 entity, 這裡用 Entity 函式建立一個新的entity物件,並且使用tableRestProxy 中的 insertEntity 把它加入你要的 table. 在建立 entity 物件的時候,可以同時加入你想要儲存的屬性資料(properties, 用 addProperty 新建並寫入你要的名稱-值組合)。

除了要存的資料外,還必須設定 entity 的 PartitionKey 和 RowKey。系統在儲存 table 的時候會自動散佈在多個儲存 node 上,因此設定 PartitionKey 可以指定讓你想要的 entity 存在同一個 node 上(擁有同一個 PartitionKey 的 entity 會存在一起),這樣在一些操作上效率會比較好。而 RowKey 則是每個 entity 在它的區段(partition, 也就是儲存的 node)中的獨特 ID.

下面這個範例示範如何建立一個新的entity, 設定它的各種屬性(properties),並且把它加入table.

require_once 'vendor\autoload.php';

use WindowsAzure\Common\ServicesBuilder;
use WindowsAzure\Common\ServiceException;
use WindowsAzure\Table\Models\Entity;
use WindowsAzure\Table\Models\EdmType;

// Create table REST proxy.
$tableRestProxy = ServicesBuilder::getInstance()->createTableService($connectionString);

$entity = new Entity();
$entity->setPartitionKey("tasksSeattle");
$entity->setRowKey("1");
$entity->addProperty("Description", null, "Take out the trash.");
$entity->addProperty("DueDate", 
                     EdmType::DATETIME, 
                     new DateTime("2012-11-05T08:15:00-08:00"));
$entity->addProperty("Location", EdmType::STRING, "Home");

try {
    $tableRestProxy->insertEntity("mytable", $entity);
}
catch(ServiceException $e){
    // Handle exception based on error codes and messages.
    // Error codes and messages are here: 
    // http://msdn.microsoft.com/zh-tw/library/windowsazure/dd179438.aspx
    $code = $e->getCode();
    $error_message = $e->getMessage();
}

除了用 insertEntity 這個函式加入新的 entity 之外,還可以用 insertOrMergeEntity 或insertOrReplaceEntity 來新增。當你要加入的entity還不存在時(沒有其它的entity有跟它一樣的PartitionKey和RowKey)這兩個函式都會把你新增的entity加入到table裡面。但是,當這個entity已經存在的時候,insertOrMergeEntity 會根據新的 entity 更新舊的的資料。已經存在的屬性(property)的值會換成新的,而還不存在的屬性會被加進去。inserOrReplaceEntity這個函式則會把舊的entity完全用新的覆蓋掉。

如果你已經做了前一個範例,下面這個範例會把entity裡面的DueDate時間更新成新的然後加入Location和Status兩個屬性。

require_once 'vendor\autoload.php';

use WindowsAzure\Common\ServicesBuilder;
use WindowsAzure\Common\ServiceException;
use WindowsAzure\Table\Models\Entity;
use WindowsAzure\Table\Models\EdmType;

// Create table REST proxy.
$tableRestProxy = ServicesBuilder::getInstance()->createTableService($connectionString);

//Create new entity.
$entity = new Entity();

// PartitionKey and RowKey are required.
$entity->setPartitionKey("tasksSeattle");
$entity->setRowKey("1");

// If entity exists, existing properties are updated with new values and
// new properties are added.Missing properties are unchanged.
$entity->addProperty("Description", null, "Take out the trash.");
$entity->addProperty("DueDate", EdmType::DATETIME, new DateTime()); // Modified the DueDate field.
$entity->addProperty("Location", EdmType::STRING, "Home");
$entity->addProperty("Status", EdmType::STRING, "Complete"); // Added Status field.

try {
    // Calling insertOrReplaceEntity, instead of insertOrMergeEntity as shown,
    // would simply replace the entity with PartitionKey "tasksSeattle" and RowKey "1".
    $tableRestProxy->insertOrMergeEntity("mytable", $entity);
}
catch(ServiceException $e){
    // Handle exception based on error codes and messages.
    // Error codes and messages are here: 
    // http://msdn.microsoft.com/zh-tw/library/windowsazure/dd179438.aspx
    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.":".$error_message."
";
}

取得entity資料:

想要取得一個entity, 只要用getEntity這個函式找尋它的PartitionKey和RowKey就可以了。

require_once 'vendor\autoload.php';

use WindowsAzure\Common\ServicesBuilder;
use WindowsAzure\Common\ServiceException;

// Create table REST proxy.
$tableRestProxy = ServicesBuilder::getInstance()->createTableService($connectionString);

try {
    $result = $tableRestProxy->getEntity("mytable", "tasksSeattle", 1);
}
catch(ServiceException $e){
    // Handle exception based on error codes and messages.
    // Error codes and messages are here: 
    // http://msdn.microsoft.com/zh-tw/library/windowsazure/dd179438.aspx
    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.":".$error_message."
";
}

$entity = $result->getEntity();

echo $entity->getPartitionKey().":".$entity->getRowKey();

取得一個區段內所有的entity:

如果想要取得一個區段內所有的entity可以用篩選功能。新增一個篩選條件 “PartitionKey eq partition_name”(在partition_name這個區段中尋找)然後用queryEntities函式去取得符合這個條件的所有entity.

require_once 'vendor\autoload.php';

use WindowsAzure\Common\ServicesBuilder;
use WindowsAzure\Common\ServiceException;

// Create table REST proxy.
$tableRestProxy = ServicesBuilder::getInstance()->createTableService($connectionString);

$filter = "PartitionKey eq 'tasksSeattle'";

try {
    $result = $tableRestProxy->queryEntities("mytable", $filter);
}
catch(ServiceException $e){
    // Handle exception based on error codes and messages.
    // Error codes and messages are here: 
    // http://msdn.microsoft.com/zh-tw/library/windowsazure/dd179438.aspx
    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.":".$error_message."
";
}

$entities = $result->getEntities();

foreach($entities as $entity){
    echo $entity->getPartitionKey().":".$entity->getRowKey()."
";
}