PHP Conference Japan 2024

pg_insert

(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)

pg_insert將陣列插入表格

描述

pg_insert(
    PgSql\Connection $connection,
    string $table_name,
    array $values,
    int $flags = PGSQL_DML_EXEC
): PgSql\Result|string|bool

pg_insert()values 的值插入由 table_name 指定的表格。

如果指定了 flags,則會對 values 應用具有指定標誌的 pg_convert()

預設情況下,pg_insert() 傳遞原始值。值必須被逸脫,否則必須在 flags 中指定 PGSQL_DML_ESCAPE 標誌。PGSQL_DML_ESCAPE 會引用和逸脫參數/識別符號。因此,表格/欄位名稱會變成區分大小寫。

請注意,逸脫或預先準備的查詢都不能保護 LIKE 查詢、JSON、陣列、Regex 等。這些參數應根據其上下文進行處理,即逸脫/驗證值。

參數

connection

一個 PgSql\Connection 實例。

table_name

要將列插入的表格名稱。表格 table_name 必須至少具有與 values 的元素數量一樣多的欄位。

values

一個 array,其鍵是表格 table_name 中的欄位名稱,其值是要插入的那些欄位的值。

flags

可以是任意數量的 PGSQL_CONV_OPTSPGSQL_DML_NO_CONVPGSQL_DML_ESCAPEPGSQL_DML_EXECPGSQL_DML_ASYNCPGSQL_DML_STRING 的組合。如果 PGSQL_DML_STRINGflags 的一部分,則會返回查詢字串。當設定 PGSQL_DML_NO_CONVPGSQL_DML_ESCAPE 時,它不會在內部呼叫 pg_convert()

回傳值

成功時返回 true,失敗時返回 false。如果透過 flags 傳遞 PGSQL_DML_STRING,則在成功時返回 string

錯誤/例外

當指定的表格無效時,會拋出 ValueError

當欄位的值或類型與 PostgreSQL 的類型不符時,會拋出 ValueErrorTypeError

變更日誌

版本 描述
8.3.0 現在,當指定的表格無效時,會拋出 ValueError 錯誤;以前會發出 E_WARNING
8.3.0 現在,當欄位的值或類型與 PostgreSQL 的類型不符時,會拋出 ValueErrorTypeError 錯誤;以前會發出 E_WARNING
8.1.0 現在返回 PgSql\Result 實例;以前,返回 resource
8.1.0 connection 參數現在期望 PgSql\Connection 實例;以前,期望 resource

範例

範例 1 pg_insert() 範例

<?php
$dbconn
= pg_connect('dbname=foo');
// 這在某種程度上是安全的,因為所有值都已逸脫。
// 但是 PostgreSQL 支援 JSON/陣列。這些透過逸脫或準備查詢都不是安全的。
$res = pg_insert($dbconn, 'post_log', $_POST, PGSQL_DML_ESCAPE);
if (
$res) {
echo
"POST 資料已成功記錄\n";
} else {
echo
"使用者一定發送了錯誤的輸入\n";
}
?>

參見

  • pg_convert() - 將關聯陣列值轉換為適合 SQL 語句的形式

新增筆記

使用者貢獻的筆記 9 筆筆記

shane at treesandthings dot com
20 年前
返回 SQL 語句,對 'rorezende at hotmail dot com' 的程式碼略作改進。此版本正確加入了布林值。它還會檢查陣列中是否確實有值,然後再將其包含在 SQL 語句中。(即:空值或空字串不會被加入到 SQL 語句中)

<?PHP
function db_build_insert($table,$array)
{

$str = "insert into $table ";
$strn = "(";
$strv = " VALUES (";
while(list(
$name,$value) = each($array)) {

if(
is_bool($value)) {
$strn .= "$name,";
$strv .= ($value ? "true":"false") . ",";
continue;
};

if(
is_string($value)) {
$strn .= "$name,";
$strv .= "'$value',";
continue;
}
if (!
is_null($value) and ($value != "")) {
$strn .= "$name,";
$strv .= "$value,";
continue;
}
}
$strn[strlen($strn)-1] = ')';
$strv[strlen($strv)-1] = ')';
$str .= $strn . $strv;
return
$str;

}
?>
skippy at zuavra dot net
19 年前
請注意以下事項:pg_insert() 和 pg_update() 會在它們處理的所有字元型欄位中加入斜線。這使得它們在 SQL 注入方面超級安全,但也會產生一些不良的後果,如下所示

如果您的一般設定是 magic_quotes_gcp=On,並且您使用 pg_insert() 或 pg_update(),您最終會得到看起來像是您使用了兩次 addslashes() 的欄位。為了解決這個問題,您可以在使用 pg_insert() 或 pg_update() 之前,先對資料使用 stripslashes()。

還有另一種替代方案,在我看來似乎更好。為什麼要讓自己在整個程式碼中忙著加入斜線、移除斜線,還要擔心 magic_quotes_gpc 是開啟還是關閉等等?當您實際上只需要在將資料推入資料庫時才需要這些斜線時,為什麼要這樣做?

因此,為什麼不從您的程式碼中移除所有的 addslashes() 和 stripslashes(),並關閉 magic_quotes_gcp。只要您始終使用 pg_insert() 和 pg_update() 來執行您的資料庫工作,您在 SQL 注入方面就是安全的,而且也不會有斜線問題。
jsnell at e-normous dot com
17 年前
如果您需要綱要支援,此函式將執行類似於 pg_insert 的操作

function pg_insert_with_schema($connection, $table, $updates)
{
$schema = 'public';
if (strpos($table, '.') !== false)
list($schema, $table) = explode('.', $table);

if (count($updates) == 0) {
$sql = "INSERT INTO $schema.\"$table\" DEFAULT VALUES";
return pg_query($sql);
} else {
$sql = "INSERT INTO $schema.\"$table\" ";

$sql .= '("';
$sql .= join('", "', array_keys($updates));
$sql .= '")';

$sql .= ' values (';
for($i = 0; $i < count($updates); $i++)
$sql .= ($i != 0? ', ':'').'$'.($i+1);
$sql .= ')';
return pg_query_params($connection, $sql, array_values($updates));
}
}
phpuser at ego dot gen dot nz
12 年前
此函式不能用於插入只有預設值的記錄,也就是說,不能使用 assoc_array 的 array()
Anonymous
3 年前
$Result = pg_query_params($db,'INSERT INTO table1 (a, b, c) VALUES ($1,$2,$3) RETURNING *', array('1','2','3');
$Row = pg_fetch_assoc($Result);
pg_insert($db, 'table2', $Row);

如果 table2 上的一個或多個欄位名稱與 table1 不同,pg_insert 會靜默失敗
mina86 at tlen dot pl
20 年前
下一個版本 :) 我的版本會檢查值是否為布林值、Null 值、字串或數值,如果其中一個值不是,則函式會傳回 false。Null 值會以 NULL 插入,布林值會以 true 或 false 插入,字串會在加入查詢字串之前加入反斜線。請注意,此函式不安全。如果您使用 $_POST 或類似的內容作為 $array,則欄位名稱可能會出現 SQL 注入。

<?php
function db_build_insert($table, $array) {
if (
count($array)===0) return false;
$columns = array_keys($array);
$values = array_values($array);
unset(
$array);

for (
$i = 0, $c = count($values); $i$c; ++$i) {
if (
is_bool($values[$i])) {
$values[$i] = $values[$i]?'true':'false';
} elseif (
is_null($values[$i])) {
$values[$i] = 'NULL';
} elseif (
is_string($values[$i])) {
$values[$i] = "'" . addslashes($values[$i]) . "'";
} elseif (!
is_numeric($values[$i])) {
return
false;
}
}

return
"INSERT INTO $table ($column_quote" . implode(', ', $columns) .
") VALUES (" . implode(', ', $values) . ")";
}
?>
excalibur at nospam dot icehouse dot net
18 年前
今天在工作時,我將此函式遇到的問題歸因於日期格式化方式。我在程式碼中指定日期的格式如下

$today = date( "Ymd" ); // ISO 8601

此格式可為 PostgreSQL 接受,正如他們的說明文件和使用 psql 的測試所驗證。但是,為了讓它在我的程式碼中運作,我必須進行以下變更

$today = date( "Y-m-d" ); // 也屬於 ISO 8601 格式
rorezende at hotmail dot com
21 年前
時間就是金錢,所以我編寫了一個類似於 PHP 中的 pg_insert 的函式(僅輸出 sql 語句)

function db_mount_insert($table,$array) {

$str = "insert into $table (";
while(list($name,$value) = each($array)) {
$str .= "$name,";
}
$str[strlen($str)-1] = ')';
$str .= " values (";
reset($array);
while(list($name,$value) = each($array)) {
if(is_string($value))
$str .= "'$value',";
else
$str .= "$value,";
}
$str[strlen($str)-1] = ')';
$str .= ";" ;

return $str;

}
ANDYCHR17 at HOTMAIL dot COM
18 年前
在 PHP 4.4.0 中嘗試執行此程式碼時遇到了一些問題

- 我無法使用屬於 SQL 保留字的欄位名稱(例如:desc、order)來執行。我被迫變更欄位名稱才能使用此函式。我無法將欄位名稱放在引號中,因為那會導致 pg_convert() 失敗。

- 在我傳遞 PGSQL_DML_EXEC 選項之前,函式會傳回 false。
To Top