PHP - проблемы с PDO с помощью bindValue()
Я пишу класс, который программно создает таблицу с определенными именами столбцов. Я использую подготовленные заявления 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, просто передавая массив параметров в $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]);
}
2 ответа
Мне кажется, что вы пытаетесь привязать к имени / столбцам таблицы, что невозможно сделать с помощью 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;
bindParam()
а также bindValue()
обработать значение по ссылке, что означает, что вы передали ему ссылку на $value
переменная, а не ее значение в тот момент, когда вы ее вызвали. Когда цикл заканчивается и вы звоните query()
, $value
будет то, что последний в $array
было.
Используйте ссылку на элемент в массиве:
$stmt->bindValue(":".$array[$param], $array[$param]);
$stmt->bindParam($param, $array[$param]);