aci_bind_by_name

aci_bind_by_name — 绑定一个 PHP 变量到一个 数据库 位置标志符

说明

aci_bind_by_name(
    resource $statement,
    string $bv_name,
    mixed &$variable,
    int $maxlength = -1,
    int $type = SQLT_CHR
): bool

将 PHP 变量 variable 绑定到位置标志符 bv_name 。绑定操作对数据库性能很重要,同时也是避免 SQL 注入安全问题的一种方式。

aci_bind_by_name() 将 PHP 变量 variable 绑定到的位置标志符 ph_name。 该变量是否会被用作输入输出是在运行时决定的,并且函数给该变量分配必要的存储空间。length参数确定该绑定的最大长度,如果将 length设为 -1,aci_bind_by_name() 会用 variable 变量的当前长度确定绑定的最大长度。

如果要绑定一个抽象数据类型(LOB/ROWID/BFILE),需要先用 aci_new_descriptor()。函数分配空间。 length没有用于抽象数据类型,应被设为 -1。type 参数告诉 数据库要使用什么样的描述符。

可能的值为:

SQLT_FILE - 对应于 BFILE;

SQLT_CFILE - 对应于 CFILE;

SQLT_CLOB - 对应于 CLOB;

SQLT_BLOB - 对应于 BLOB;

SQLT_ROWID - 对应于 ROWID;

SQLT_NTY - 对应于有名字的数据类型;

SQLT_INT - 对应于 integers;

SQLT_CHR - 对应于 VARCHARs;

SQLT_BIN - 对应于 RAW 列;

SQLT_LNG - 对应于 LONG 列;

SQLT_LBI - 对应于 LONG RAW 列;

SQLT_RSET - 对应于游标,是之前由 aci_new_cursor() 创建的。

范例

示例 #1 aci_bind_by_name() 例子

<?php
/* aci_bind_by_name example thies at thieso dot net (980221)
  inserts 3 records into emp, and uses the ROWID for updating the
  records just after the insert.
*/

$conn = aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;

$stmt = aci_parse($conn, "
                          INSERT INTO
                                     emp (empno, ename)
                                              VALUES
                                     (:empno,:ename)
                            RETURNING
                                     ROWID
                                 INTO
                                     :rid
                                         ");

$data = array(
              1111 => "Larry",
              2222 => "Bill",
              3333 => "Jim"
             );

$rowid = aci_new_descriptor($conn, OCI_D_ROWID);

aci_bind_by_name($stmt, ":empno", $empno, 32);
aci_bind_by_name($stmt, ":ename", $ename, 32);
aci_bind_by_name($stmt, ":rid",   $rowid, -1, OCI_B_ROWID);

$update = aci_parse($conn, "
                            UPDATE
                                  emp
                               SET
                                  sal = :sal
                             WHERE
                                  ROWID = :rid
                             ");
aci_bind_by_name($update, ":rid", $rowid, -1, OCI_B_ROWID);
aci_bind_by_name($update, ":sal", $sal,   32);

$sal = 10000;

foreach ($data as $empno => $ename) {
    aci_execute($stmt);
    aci_execute($update);
}

$rowid->free();

aci_free_statement($update);
aci_free_statement($stmt);

$stmt = aci_parse($conn, "
                       SELECT
                             *
                         FROM
                             emp
                        WHERE
                             empno
                           IN
                             (1111,2222,3333)
                           ");
aci_execute($stmt);

while ($row = aci_fetch_assoc($stmt)) {
    var_dump($row);
}

oci_free_statement($stmt);

/* delete our "junk" from the emp table.... */
$stmt = aci_parse($conn, "
                       DELETE FROM
                                  emp
                             WHERE
                                  empno
                                IN
                                  (1111,2222,3333)
                                ");
aci_execute($stmt);
aci_free_statement($stmt);

aci_close($conn);
?>

记住,本函数删除了行尾的空白字符。见以下例子:

示例 #2 aci_bind_by_name() 例子

<?php
$connection =aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;
$query = "INSERT INTO test_table VALUES(:id, :text)";

$statement = aci_parse($query);
aci_bind_by_name($statement, ":id", 1);
aci_bind_by_name($statement, ":text", "trailing spaces follow     ");
aci_execute($statement);
/*
 This code will insert into DB string 'trailing spaces follow', without
 trailing spaces
*/
?>

示例 #3 aci_bind_by_name() 例子

<?php
$connection = aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;
$query = "INSERT INTO test_table VALUES(:id, 'trailing spaces follow      ')";

$statement = aci_parse($query);
aci_bind_by_name($statement, ":id", 1);
aci_execute($statement);
/*
 And this code will add 'trailing spaces follow      ', preserving
 trailing whitespaces
*/
?>

警告

警告: 不要将 magic_quotes_gpc 或 addslashes() 与 aci_bind_by_name() 同时使用,因为不需要转义,任何自动加上的引号都会被写入数据库中,因为 aci_bind_by_name() 不能分辨有意加上的引号和魔术引号。

成功时返回 true, 或者在失败时返回 false

注意:
在 PHP 5.0.0 之前的版本必须使用 acibindbyname() 替代本函数。
该函数名仍然可用,为向下兼容作为 aci_bind_by_name() 的别名。不过其已被废弃,不推荐使用。

参数

statement

有效的ACI8语句标识符。

bv_name

语句中使用的带冒号前缀的绑定变量占位符。冒号在 bv_name 中是可选的。不使用问号作为占位符。

variable

要与 bv_name 关联的PHP变量

maxlength

设置数据的最大长度。如果将其设置为-1,此函数将使用变量的当前长度来设置最大长度。 在这种情况下,当调用**aci_bind_by_name()**时,变量必须存在并包含数据。

type

数据库将数据视为的数据类型。使用的默认 type 是**SQLT_CHR**。如果可能,数据库将在该类型和数据库列(或PL/SQL变量类型)之间转换数据。

如果需要绑定抽象数据类型(LOB/ROWID/BFILE),则需要首先使用aci_new_descriptor()函数分配它。length不用于抽象数据类型,应设置为-1。

类型的可能值为:

SQLT_FILE - 对应于 BFILE;

SQLT_CFILE - 对应于 CFILE;

SQLT_CLOB - 对应于 CLOB;

SQLT_BLOB - 对应于 BLOB;

SQLT_ROWID - 对应于 ROWID;

SQLT_NTY - 对应于有名字的数据类型;

SQLT_INT - 对应于 integers;

SQLT_CHR - 对应于 VARCHARs;

SQLT_BIN - 对应于 RAW 列;

SQLT_LNG - 对应于 LONG 列;

SQLT_LBI - 对应于 LONG RAW 列;

SQLT_RSET - 对应于游标,是之前由 aci_new_cursor() 创建的。

返回值

成功时返回 true, 或者在失败时返回 false。

范例

示例 #4 使用aci_bind_by_name()插入数据

<?php

// Create the table with:
//   CREATE TABLE mytab (id NUMBER, text VARCHAR2(40));

$conn = aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;
if (!$conn) {
    $m = aci_error();
    trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

$stid = aci_parse($conn,"INSERT INTO mytab (id, text) VALUES(:id_bv, :text_bv)");

$id = 1;
$text = "Data to insert     ";
aci_bind_by_name($stid, ":id_bv", $id);
aci_bind_by_name($stid, ":text_bv", $text);
aci_execute($stid);

// Table now contains: 1, 'Data to insert     '

?>

示例 #5多次执行绑定一次

<?php

// Create the table with:
//   CREATE TABLE mytab (id NUMBER);

$conn = aci_connect('hr', 'welcome', 'localhost/XE');
if (!$conn) {
    $m = aci_error();
    trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

$a = array(1,3,5,7,11);  // data to insert

$stid = aci_parse($conn, 'INSERT INTO mytab (id) VALUES (:bv)');
aci_bind_by_name($stid, ':bv', $v, 20);
foreach ($a as $v) {
    $r = aci_execute($stid, OCI_DEFAULT);  // don't auto commit
}
aci_commit($conn); // commit everything at once

// Table contains five rows: 1, 3, 5, 7, 11

aci_free_statement($stid);
aci_close($conn);

?>

示例 #6 使用foreach()循环绑定

<?php

$conn = aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;
if (!$conn) {
    $m = aci_error();
    trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

$sql = 'SELECT * FROM departments WHERE department_name = :dname AND location_id = :loc';
$stid = aci_parse($conn, $sql);

$ba = array(':dname' => 'IT Support', ':loc' => 1700);

foreach ($ba as $key => $val) {
    aci_bind_by_name($stid, $key, $ba[$key]);
}

aci_execute($stid);
$row = aci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS);
foreach ($row as $item) {
    print $item."<br>\n";
}

aci_free_statement($stid);
aci_close($conn);

?>

示例 #7 WHERE子句中的绑定

<?php

$conn = aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;
if (!$conn) {
    $m = aci_error();
    trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

$sql = 'SELECT last_name FROM employees WHERE department_id = :didbv ORDER BY last_name';
$stid = aci_parse($conn, $sql);
$didbv = 60;
aci_bind_by_name($stid, ':didbv', $didbv);
aci_execute($stid);
while (($row = aci_fetch_array($stid, OCI_ASSOC)) != false) {
    echo $row['LAST_NAME'] ."<br>\n";
}

// Output is
//    Austin
//    Ernst
//    Hunold
//    Lorentz
//    Pataballa

aci_free_statement($stid);
aci_close($conn);

?>

示例 #8 与LIKE子句绑定

<?php

$conn = aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;
if (!$conn) {
    $m = aci_error();
    trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

// Find all cities that begin with 'South'
$stid = aci_parse($conn, "SELECT city FROM locations WHERE city LIKE :bv");
$city = 'South%';  // '%' is a wildcard in SQL
aci_bind_by_name($stid, ":bv", $city);
aci_execute($stid);
aci_fetch_all($stid, $res);

foreach ($res['CITY'] as $c) {
    print $c . "<br>\n";
}
// Output is
//   South Brunswick
//   South San Francisco
//   Southlake

aci_free_statement($stid);
aci_close($conn);

?>

示例 #9 与REGEXP_LIKE绑定

<?php

$conn = aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;
if (!$conn) {
    $m = aci_error();
    trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

// Find all cities that contain 'ing'
$stid = aci_parse($conn, "SELECT city FROM locations WHERE REGEXP_LIKE(city, :bv)");
$city = '.*ing.*';
aci_bind_by_name($stid, ":bv", $city);
aci_execute($stid);
aci_fetch_all($stid, $res);

foreach ($res['CITY'] as $c) {
    print $c . "<br>\n";
}
// Output is
//   Beijing
//   Singapore

aci_free_statement($stid);
aci_close($conn);

?>

对于少量固定数量的IN子句条件,请使用单独的绑定变量。 运行时未知的值可以设置为NULL。这允许所有应用程序用户使用一条语句,从而最大限度地提高数据库缓存效率。

示例 #10 在in子句中绑定多个值

<?php

$conn = aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;
if (!$conn) {
    $m = aci_error();
    trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

$sql = 'SELECT last_name FROM employees WHERE employee_id in (:e1, :e2, :e3)';
$stid = aci_parse($conn, $sql);
$mye1 = 103;
$mye2 = 104;
$mye3 = NULL; // pretend we were not given this value
aci_bind_by_name($stid, ':e1', $mye1);
aci_bind_by_name($stid, ':e2', $mye2);
aci_bind_by_name($stid, ':e3', $mye3);
aci_execute($stid);
aci_fetch_all($stid, $res);
foreach ($res['LAST_NAME'] as $name) {
    print $name ."<br>\n";
}

// Output is
//   Ernst
//   Hunold

aci_free_statement($stid);
aci_close($conn);

?>

示例 #11 绑定查询返回的ROWID

<?php

// Create the table with:
//   CREATE TABLE mytab (id NUMBER, salary NUMBER, name VARCHAR2(40));
//   INSERT INTO mytab (id, salary, name) VALUES (1, 100, 'Chris');
//   COMMIT;

$conn = aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;
if (!$conn) {
    $m = aci_error();
    trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

$stid = aci_parse($conn, 'SELECT ROWID, name FROM mytab WHERE id = :id_bv FOR UPDATE');
$id = 1;
aci_bind_by_name($stid, ':id_bv', $id);
aci_execute($stid);
$row = aci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS);
$rid = $row['ROWID'];
$name = $row['NAME'];

// Change name to upper case & save the changes
$name = strtoupper($name);
$stid = aci_parse($conn, 'UPDATE mytab SET name = :n_bv WHERE ROWID = :r_bv');
aci_bind_by_name($stid, ':n_bv', $name);
aci_bind_by_name($stid, ':r_bv', $rid, -1, OCI_B_ROWID);
aci_execute($stid);

// The table now contains 1, 100, CHRIS

aci_free_statement($stid);
aci_close($conn);

?>

示例 #12 在INSERT上绑定ROWID

<?php

// This example inserts an id & name, and then updates the salary
// Create the table with:
//   CREATE TABLE mytab (id NUMBER, salary NUMBER, name VARCHAR2(40));
//
// Based on original ROWID example by thies at thieso dot net (980221)

$conn = aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;
if (!$conn) {
    $m = aci_error();
    trigger_error(htmlentities($m['message']), E_USER_ERROR);
}

$sql = "INSERT INTO mytab (id, name) VALUES(:id_bv, :name_bv)
        RETURNING ROWID INTO :rid";

$ins_stid = aci_parse($conn, $sql);

$rowid = aci_new_descriptor($conn, OCI_D_ROWID);
aci_bind_by_name($ins_stid, ":id_bv",   $id,    10);
aci_bind_by_name($ins_stid, ":name_bv", $name,  32);
aci_bind_by_name($ins_stid, ":rid",     $rowid, -1, OCI_B_ROWID);

$sql = "UPDATE mytab SET salary = :salary WHERE ROWID = :rid";
$upd_stid = aci_parse($conn, $sql);
aci_bind_by_name($upd_stid, ":rid", $rowid, -1, OCI_B_ROWID);
aci_bind_by_name($upd_stid, ":salary", $salary,   32);

// ids and names to insert
$data = array(1111 => "Larry",
              2222 => "Bill",
              3333 => "Jim");

// Salary of each person
$salary = 10000;

// Insert and immediately update each row
foreach ($data as $id => $name) {
    aci_execute($ins_stid);
    aci_execute($upd_stid);
}

$rowid->free();
aci_free_statement($upd_stid);
aci_free_statement($ins_stid);

// Show the new rows
$stid = aci_parse($conn, "SELECT * FROM mytab");
aci_execute($stid);
while ($row = aci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS)) {
    var_dump($row);
}

aci_free_statement($stid);
aci_close($conn);

?>

示例 #13 PL/SQL存储函数的绑定

<?php

//  Before running the PHP program, create a stored function in
//  SQL*Plus or SQL Developer:
//
//  CREATE OR REPLACE FUNCTION myfunc(p IN NUMBER) RETURN NUMBER AS
//  BEGIN
//      RETURN p * 3;
//  END;

$conn = aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;
if (!$conn) {
    $e = aci_error();
    trigger_error(htmlentities($e['message']), E_USER_ERROR);
}

$p = 8;

$stid = aci_parse($conn, 'begin :r := myfunc(:p); end;');
aci_bind_by_name($stid, ':p', $p);

// The return value is an OUT bind. The default type will be a string
// type so binding a length 40 means that at most 40 digits will be
// returned.
aci_bind_by_name($stid, ':r', $r, 40);

aci_execute($stid);

print "$r\n";   // prints 24

aci_free_statement($stid);
aci_close($conn);

?>

示例 #14 PL/SQL存储过程的绑定参数

<?php

//  Before running the PHP program, create a stored procedure in
//  SQL*Plus or SQL Developer:
//
//  CREATE OR REPLACE PROCEDURE myproc(p1 IN NUMBER, p2 OUT NUMBER) AS
//  BEGIN
//      p2 := p1 * 2;
//  END;

$conn = aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;
if (!$conn) {
    $e = aci_error();
    trigger_error(htmlentities($e['message']), E_USER_ERROR);
}

$p1 = 8;

$stid = aci_parse($conn, 'begin myproc(:p1, :p2); end;');
aci_bind_by_name($stid, ':p1', $p1);

// The second procedure parameter is an OUT bind. The default type
// will be a string type so binding a length 40 means that at most 40
// digits will be returned.
aci_bind_by_name($stid, ':p2', $p2, 40);

aci_execute($stid);

print "$p2\n";   // prints 16

aci_free_statement($stid);
aci_close($conn);

?>

示例 #15 绑定CLOB列

<?php

// Before running, create the table:
//     CREATE TABLE mytab (mykey NUMBER, myclob CLOB);

$conn = aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;
if (!$conn) {
    $e = aci_error();
    trigger_error(htmlentities($e['message']), E_USER_ERROR);
}

$mykey = 12343;  // arbitrary key for this example;

$sql = "INSERT INTO mytab (mykey, myclob)
        VALUES (:mykey, EMPTY_CLOB())
        RETURNING myclob INTO :myclob";

$stid = aci_parse($conn, $sql);
$clob = aci_new_descriptor($conn, OCI_D_LOB);
aci_bind_by_name($stid, ":mykey", $mykey, 5);
aci_bind_by_name($stid, ":myclob", $clob, -1, OCI_B_CLOB);
aci_execute($stid, OCI_DEFAULT);
$clob->save("A very long string");

aci_commit($conn);

// Fetching CLOB data

$query = 'SELECT myclob FROM mytab WHERE mykey = :mykey';

$stid = aci_parse ($conn, $query);
aci_bind_by_name($stid, ":mykey", $mykey, 5);
aci_execute($stid);

print '<table border="1">';
while ($row = aci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_LOBS)) {
    print '<tr><td>'.$row['MYCLOB'].'</td></tr>';
    // In a loop, freeing the large variable before the 2nd fetch reduces PHP's peak memory usage
    unset($row);
}
print '</table>';

?>

示例 #16 绑定PL/SQL布尔

<?php

$conn = aci_connect('sysdba', 'szoscar55', 'localhost:2003/OSRDB')  ;
if (!$conn) {
    $e = aci_error();
    trigger_error(htmlentities($e['message']), E_USER_ERROR);
}

$plsql =
  "begin
    :output1 := true;
    :output2 := false;
   end;";

$s = aci_parse($c, $plsql);
aci_bind_by_name($s, ':output1', $output1, -1, OCI_B_BOL);
aci_bind_by_name($s, ':output2', $output2, -1, OCI_B_BOL);
aci_execute($s);
var_dump($output1);  // true
var_dump($output2);  // false

?>

返回值

成功时返回 true, 或者在失败时返回 false

注释

警告

警告 不要同时使用magic_quotes_gpc或addslashes()和aci_bind_by_name(),因为不需要引号。 由于aci_bind_by_name()逐字插入数据,并且不会删除引号或转义字符,因此任何神奇应用的引号都将写入数据库。

注意:

如果在WHERE子句中将字符串绑定到CHAR列,请记住数据库对CHAR列使用空白填充的比较语义。要使WHERE子句成功,您的PHP变量应该空白填充到与列相同的宽度。

注意:

PHP变量参数是一个引用。某些形式的循环无法按预期工作
<?php
foreach ($myarray as $key => $value)  {
    aci_bind_by_name($stid, $key, $value);
}
?>

这将每个键绑定到$value的位置,因此所有绑定的变量最终都指向最后一个循环迭代的值。相反,请使用以下内容:

<?php
foreach ($myarray as $key => $value) {
    aci_bind_by_name($stid, $key, $myarray[$key]);
}
?>

参见