我想从以下PHP
代码创建一个触发器。
$sql = 'delimiter $$';
$pdo->exec($sql);
$sql = 'create trigger avoid_empty_employee_insert before insert on `employee`
for each row begin
if name = "" then set name = null; end if;
end$$';
$pdo->exec($sql);
$sql = 'delimiter ;';
$pdo->exec($sql);
当我在MySQL
中运行代码时,它就工作了,并且创建了触发器。
PHP显示以下错误。
SQLSTATE[42000]:语法错误或访问违规:1064您的SQL语法有错误;查看手册对应于您的MySQL服务器版本,以获得正确的语法在第1行使用"分隔符$$"附近
我该怎么修?
通过API执行语句时,绝对不要尝试更改分隔符。DELIMITER
是mysql客户端内置的命令,mysql服务器端解析器无法识别。
你根本不需要它。DELIMITER
的目的是消除可能出现在触发器或存储例程主体内的分号的歧义。由于API用于一次执行一条语句,因此不存在歧义。无论如何,SQL解析器只是将整个字符串视为一条语句。
同样,不要以$$
结束create触发器语句。您不需要任何语句终止符,但SQL解析器接受;
作为可选的语句终止符
下一个问题是,当你在触发器中使用列名时,你必须用NEW.
或OLD.
作为前缀——在插入触发器中,你只能使用NEW.
。如果你不给列加前缀,MySQL假设你想设置一个像tmpdir
或slow_query_log
这样的系统变量。
如果您仍然得到1193错误,我建议您不要将对name
列的两个引用都更改为NEW.name
。
我使用PHP 5.4.24和MySQL 5.6.20测试了以下内容,结果成功了:
$sql = "create trigger avoid_empty_employee_insert before insert on `employee`
for each row begin
if NEW.name = '' then set NEW.name = null; end if;
end";
$pdo->exec($sql);
您不需要对name
的列名进行定界,因为它不是MySQL的保留字。保留字集已记录在案。
尝试一下:
$sql = 'create trigger avoid_empty_employee_insert before insert on `employee`
for each row begin
if name = "" then set name = null; end if; END;';
$pdo->exec($sql);
由于您使用代码创建触发器,因此可能不需要设置/重置DELIMITER
。
只需忽略php代码中更改这些行即可。
您的代码仅变为:
$sql = 'create trigger avoid_empty_employee_insert before insert on `employee`
for each row begin
if NEW.`name` = "" then set NEW.`name` = null; end if;
end$$';
$pdo->exec($sql);
也许这有助于:
$sql = "delimiter //'n";
$pdo->exec($sql);
$sql = "create trigger avoid_empty_employee_insert before insert on employee'n
for each row'n
begin'n
if new.name = '' then'n
set new.name = null;'n
end if;'n
end//'n";
$pdo->exec($sql);
$sql = 'delimiter ;';
$pdo->exec($sql);
由于您使用代码创建触发器,因此可能不需要设置/重置DELIMITER
。更改DELIMITER对CLI非常重要。
只需忽略php代码中更改这些行即可。
您的代码仅变为:
$sql = 'create trigger `avoid_empty_employee_insert` before insert
on `employee`
for each row
begin
if `name` = "" then set `name` = null; end if;
end';
$pdo->exec($sql);