Я использую PHP PDO с T-SQL (SQL Server 2017).
Структура таблицы
id | ip | datetime
Вот код
$query ="MERGE INTO ". $this->table_name ." WITH (HOLDLOCK) AS target
USING (SELECT ip=:ip , [datetime]=:datetime ) AS source
ON target.ip = source.ip
WHEN MATCHED
THEN UPDATE
SET [datetime] = :datetime
WHEN NOT MATCHED
THEN INSERT (ip, [datetime])
VALUES (:ip, :datetime);";
// prepare query
$stmt = $this->conn->prepare($query);
// sanitize
$this->datetime=date('Y-m-d H:i:s');
$this->ip=htmlspecialchars(strip_tags($this->ip));
// bind values
$stmt->bindParam(":datetime", $this->datetime);
$stmt->bindParam(":ip", $this->ip);
// execute query
if($stmt->execute()){
return true;
}
return false;
Когда я использую sql profiler 2017, я вижу запрос, который он выполняет, который
MERGE INTO online WITH (HOLDLOCK) AS target
USING (SELECT ip='10.28.1.67' , [datetime]='2019-01-16 16:32:07' ) AS source
ON target.ip = source.ip
WHEN MATCHED
THEN UPDATE
SET [datetime] = '2019-01-16 16:32:07'
WHEN NOT MATCHED
THEN INSERT (ip, [datetime])
VALUES ('10.28.1.67', '2019-01-16 16:32:07');
Когда я сам выполняю этот сценарий в Sql Server Management Studio 2017, он успешно выполняется (при совпадении, а когда нет).
Однако метод $stmt->execute()
возвращается false
и это не меняет таблицу. И я знаю, что $stmt->execute()
возвращается false
когда запрос не успешен.
В чем может быть проблема?
РЕДАКТИРОВАТЬ: Теперь я получаю код ошибки «07002», который означает «Недопустимый список параметров вызова или блок управления».
Я изменил код на
$query ="MERGE INTO ". $this->table_name ." WITH (HOLDLOCK) AS target
USING (SELECT ip='". $this->ip."' , [datetime]='". $this->datetime."' ) AS source
ON target.ip = source.ip
WHEN MATCHED
THEN UPDATE
SET [datetime] = '". $this->datetime."'
WHEN NOT MATCHED
THEN INSERT (ip, [datetime])
VALUES ('". $this->ip."', '". $this->datetime."');";
$stmt = $this->conn->prepare($query);
Это работает. Однако в чем проблема с первым запросом? Я не хочу использовать конкатенацию
Задача ещё не решена.
Других решений пока нет …