1

特定の列名を指定してテーブルをプログラムで作成するクラスを作成しています。いくつかの問題を引き起こしているように見える PDO 準備済みステートメントを使用しています。

基本的な手順は次のとおりです。

// create a query string to be sent to $pdo->prepare
$sql =
'CREATE TEMP TABLE :tmp_table_name (
  :person_id bigint,
  :encntr_id bigint,
  :prsnl_id bigint,
  :program_detail text,
  :program_name text
);';
$stmt = $pdo->prepare($sql);

// Bind table name
$stmt->bindValue(':tmp_table_name', 'tmp_patients', PDO::PARAM_STR);

// Bind column names
$columnNames = [
  'person_id',
  'encnt_id',
  'prsnl_id',
  'program_detail',
  'program_name',
];
foreach($columnNames as $name) {
    $stmt->bindValue(':'.$name, $name, PDO::PARAM_STR);
}

$ret = $stmt->execute();
// $ret is false! The statement fails.

$stmt->errorInfo()[2]表示される内容は次のとおりです。

ERROR:  syntax error at or near "$1"
LINE 1: CREATE TEMP TABLE $1 ($2 bigint,
$3 bigint,
$4 bigint,
$5 text,
$6 te...

$1、$2、$3 などがクエリに表示されるのはなぜですか? この PDO ステートメントをさらにデバッグする方法に関するヒントはありますか?

更新 bindParam を使用せず、params の配列を $stmt->execute() に渡すだけで、別のアプローチを試みています。それでも同じエラーが発生しますが...

$stmt = $this->pdo->prepare($this->createSql);

$keys = [];
// Bind column names
foreach($this->columnNames as $name) {
    $keys[] = ':'.$name;
}
$params = array_combine($keys, $this->columnNames);

// Bind table name
$params[':tmp_table_name'] = 'tmp_'.$this->objName;

$ret = $stmt->execute($params);
if (!$ret) {
    throw new Exception('execSchema() failed! '. $stmt->errorInfo()[2]);
}
4

2 に答える 2

5

テーブル名/列にバインドしようとしているように見えますが、これは PDO を使用して行うことはできません。値をプレースホルダーにバインドすることしかできません。

ここのコードに見られるように:

// Bind table name
$stmt->bindValue(':tmp_table_name', 'tmp_patients', PDO::PARAM_STR);

うまくいくはずのように感じますが、そうではありません。

たとえば、これは機能しません:

$sql = "insert into mytable (:thing1) values (:thing2);
$stmt->bindValue(':thing1', 'column_name' ); // this would not
$stmt->bindValue(':thing2', 'column_value' ); // this would have (on its own)

ただし、次のようなものは機能し、ソリューションまたはそのようなものを提供する必要があります。

// imagine an incoming POST load like this:
$cols = ['fname','lname'];

$array_cnt = count($cols);  // 2
$sql = 'INSERT INTO mytable ('.join(',', $cols).') ';

// and then that number of placeholders used 
$sql .= 'VALUES (' . join( array_fill( 0, $array_cnt, '?' ), ', ' ) . ')'; 

echo $sql;
于 2012-08-02T20:24:11.910 に答える
0

bindParam()値を参照によって処理します。これは、呼び出したときの値ではなくbindValue()、変数への参照を渡したことを意味します。$valueループが終了してを呼び出すとquery()$valueの最後のループになります$array

配列内のアイテムへの参照を使用します。

$stmt->bindValue(":".$array[$param], $array[$param]);
$stmt->bindParam($param, $array[$param]);
于 2012-08-02T19:42:41.410 に答える