簡體   English   中英

如何將動態構造的ext / mysql查詢轉換為PDO准備的語句?

[英]How do I convert a dynamically constructed ext/mysql query to a PDO prepared statement?

我正在將一些使用ext / mysql的代碼( mysql_*()函數)轉換為PDO和准備好的語句。 以前,當我動態構建查詢時,我只是通過mysql_real_escape_string()傳遞了我的字符串並將其直接放入查詢中,但是現在我發現我需要在執行查詢時將值作為數組傳遞,或者在執行之前綁定變量。

如何轉換舊代碼以使用新的數據庫驅動程序?

將您的查詢從ext / mysql遷移到PDO准備好的語句,需要在許多方面采用新方法。 在這里,我將介紹一些經常需要執行的常見任務。 這絕不是窮舉來匹配每種可能的情況,僅旨在演示在動態生成查詢時可以采用的某些技術。

在開始之前,請記住一些注意事項-如果某些操作不正確,請在詢問問題之前檢查此列表!

  • 如果沒有顯式禁用模擬准備,則查詢比使用mysql_real_escape_string()更安全 請參閱此以獲取完整說明。
  • 不可能在單個查詢中混合使用命名占位符和問號占位符。 在開始構建查詢之前,您必須決定使用另一個查詢,不能半途而廢。
  • 准備好的語句中的占位符只能用於值,而不能用於對象名。 換句話說,您不能使用占位符動態指定數據庫,表,列或函數名稱,或任何SQL關鍵字。 通常,如果發現需要這樣做,則應用程序的設計是錯誤的,因此需要重新檢查。
  • 用於指定數據庫/表/列標識符的任何變量都不應直接來自用戶輸入。 換句話說,請勿使用$_POST$_GET$_COOKIE或任何其他來自外部源的數據來指定列名。 您應該先對這些數據進行預處理,然后再使用它來構建動態查詢。
  • PDO命名占位符在查詢中指定為:name 將數據傳遞執行時,相應的數組鍵可以選擇包含前導: ,但這不是必需的。 占位符名稱應僅包含字母數字字符。
  • 命名占位符不能在查詢中多次使用。 要多次使用相同的值,必須使用多個不同的名稱。 如果查詢中包含許多重復的值,請考慮改用問號占位符。
  • 使用問號占位符時,傳遞值的順序很重要。 同樣重要的是要注意占位符位置是1索引,而不是0索引。

下面的所有示例代碼均假定已建立數據庫連接,並且相關的PDO實例存儲在變量$db


使用關聯數組作為列/值列表

最簡單的方法是使用命名占位符。

使用ext / mysql時,可以在構造查詢時轉義這些值,並將轉義的值直接放入查詢中。 在構造PDO准備語句時,我們使用數組鍵來指定占位符名稱,因此我們可以將數組直接傳遞給PDOStatement::execute()

對於此示例,我們有一個由三個鍵/值對組成的數組,其中鍵代表列名,而值代表列的值。 我們要選擇所有列匹配的所有行(數據具有OR關系)。

// The array you want to use for your field list
$data = array (
  'field1' => 'value1',
  'field2' => 'value2',
  'field3' => 'value3'
);

// A temporary array to hold the fields in an intermediate state
$whereClause = array();

// Iterate over the data and convert to individual clause elements
foreach ($data as $key => $value) {
    $whereClause[] = "`$key` = :$key";
}

// Construct the query
$query = '
  SELECT *
  FROM `table_name`
  WHERE '.implode(' OR ', $whereClause).'
';

// Prepare the query
$stmt = $db->prepare($query);

// Execute the query
$stmt->execute($data);

使用數組構造IN (<value list>)子句的IN (<value list>)

實現此目的的最簡單方法是使用問號占位符。

在這里,我們有一個5個字符串的數組,要與給定的列名稱進行匹配,並返回該列值至少匹配5個數組值之一的所有行。

// The array of values
$data = array (
  'value1',
  'value2',
  'value3',
  'value4',
  'value5'
);

// Construct an array of question marks of equal length to the value array
$placeHolders = array_fill(0, count($data), '?');

// Normalise the array so it is 1-indexed
array_unshift($data, '');
unset($data[0]);

// Construct the query
$query = '
  SELECT *
  FROM `table_name`
  WHERE `field` IN ('.implode(', ', $placeHolders).')
';

// Prepare the query
$stmt = $db->prepare($query);

// Execute the query
$stmt->execute($data);

如果您已經確定要使用帶有命名占位符的查詢,則該技術會稍微復雜一點,但不會太多。 您只需要遍歷數組即可將其轉換為關聯數組並構造命名的占位符。

// The array of values
$data = array (
  'value1',
  'value2',
  'value3',
  'value4',
  'value5'
);

// Temporary arrays to hold the data
$placeHolders = $valueList = array();

// Loop the array and construct the named format
for ($i = 0, $count = count($data); $i < $count; $i++) {
  $placeHolders[] = ":list$i";
  $valueList["list$i"] = $data[$i];
}

// Construct the query
$query = '
  SELECT *
  FROM `table_name`
  WHERE `field` IN ('.implode(', ', $placeHolders).')
';

// Prepare the query
$stmt = $db->prepare($query);

// Execute the query
$stmt->execute($valueList);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM