MySQL 5.7 上的存储过程语法无效,但适用于 MariaDB
Invalid stored procedure syntax on MySQL 5.7 but works on MariaDB
我正在尝试编写一个 MySQL 脚本来将管理员用户添加到服务器上的每个 WordPress 数据库并更新用户名中的用户信息已经存在。
我制作了以下脚本,它可以在 MariaDB 10.2.31 和 innodb_version 5.7.29 的服务器上运行,但它不能在 运行 MySQL Community Server 5.7 的服务器上运行.29,我收到一条错误消息:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF EXISTS (SELECT * FROM cpaneluser_wp.wp_users WHERE user_login = 'newwpuser') THEN' at line 1
这是创建存储过程的脚本:
-- Create and update a WordPress administrator across all databases
USE mysql;
delimiter $$
DROP PROCEDURE IF EXISTS ensure_global_wp_user $$
CREATE PROCEDURE ensure_global_wp_user(
IN username VARCHAR(255),
IN email VARCHAR(255),
IN password VARCHAR(255),
IN nicename VARCHAR(255),
IN displayname VARCHAR(255)
)
BEGIN
DECLARE current_schema VARCHAR(255);
DECLARE finished INTEGER DEFAULT 0;
DECLARE wp_schemas CURSOR FOR
SELECT DISTINCT table_schema
FROM INFORMATION_SCHEMA.tables
WHERE table_name = 'wp_users';
DECLARE CONTINUE HANDLER
FOR NOT FOUND
SET finished = 1;
OPEN wp_schemas;
DROP TEMPORARY TABLE IF EXISTS exec_results;
CREATE TEMPORARY TABLE IF NOT EXISTS exec_results (
username VARCHAR(255),
dbname VARCHAR(255),
action VARCHAR(255)
);
loopSchemas: LOOP
FETCH wp_schemas INTO current_schema;
IF finished = 1 THEN
LEAVE loopSchemas;
END IF;
SET @expression = CONCAT("
IF EXISTS (SELECT * FROM ",current_schema,".wp_users WHERE user_login = '",username,"') THEN
UPDATE ",current_schema,".wp_users
SET
user_pass = MD5('",password,"'),
user_email = '",email,"',
user_nicename = '",nicename,"',
display_name = '",displayname,"'
WHERE user_login = '",username,"';
INSERT INTO exec_results VALUES ('",username,"','",current_schema,"','updated');
ELSE
INSERT INTO ",current_schema,".wp_users (user_login, user_pass, user_nicename, user_email, user_status, display_name, user_registered) VALUES
('",username,"', MD5('",password,"'), '",nicename,"', '",email,"', '0', '",displayname,"', NOW());
SET @user_insert_id = LAST_INSERT_ID();
INSERT INTO ",current_schema,".wp_usermeta (user_id, meta_key, meta_value) VALUES
(@user_insert_id, 'wp_capabilities', 'a:1:{s:13:\"administrator\";b:1;}');
INSERT INTO ",current_schema,".wp_usermeta (user_id, meta_key, meta_value) VALUES
(@user_insert_id, 'wp_user_level', '10');
INSERT INTO exec_results VALUES ('",username,"','",current_schema,"','added');
END IF;
");
PREPARE stmt FROM @expression;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP loopSchemas;
CLOSE wp_schemas;
SELECT * FROM exec_results;
END $$
delimiter ;
你可以这样称呼它:
-- Create or update the newwpuser user on all wordpress databases
call ensure_global_wp_user('newwpuser', 'newwpuser@example.com', 'newpassword', 'newwpuser', 'newwpuser');
是否有不同的语法来实现此目的?我也尝试将 sql_mode
设置为 ''
,但没有任何区别。
您的@expression 在mysql.
中没有有效代码
试试这个,当然没有你的桌子我无法完全测试它
现在我首先通过另一个准备好的语句确定,如果用户存在,这个 returns 1 表示存在或 0 当 not.this 停在@res.
并使用它确定我应该使用和更新的方式,当存在时或不插入时。
Thbis 应该也可以在 mariadb 中使用。
DROP procedure IF EXISTS `ensure_global_wp_user`;
DELIMITER $$
USE `testdb`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `ensure_global_wp_user`(
IN username VARCHAR(255),
IN email VARCHAR(255),
IN password VARCHAR(255),
IN nicename VARCHAR(255),
IN displayname VARCHAR(255)
)
BEGIN
DECLARE current_schema VARCHAR(255);
DECLARE finished INTEGER DEFAULT 0;
DECLARE wp_schemas CURSOR FOR
SELECT DISTINCT table_schema
FROM INFORMATION_SCHEMA.tables
WHERE table_name = 'wp_users';
DECLARE CONTINUE HANDLER
FOR NOT FOUND
SET finished = 1;
OPEN wp_schemas;
DROP TEMPORARY TABLE IF EXISTS exec_results;
CREATE TEMPORARY TABLE IF NOT EXISTS exec_results (
username VARCHAR(255),
dbname VARCHAR(255),
action VARCHAR(255)
);
loopSchemas: LOOP
FETCH wp_schemas INTO current_schema;
IF finished = 1 THEN
LEAVE loopSchemas;
END IF;
SET @sql = CONCAT("SELECT EXISTS (SELECT * FROM ",current_schema,".wp_users WHERE user_login = '",username,"') INTO @res;");
PREPARE stmt FROM @sql;
EXECUTE stmt;
IF @res = 1 THEN
SET @expression = CONCAT("UPDATE ",current_schema,".wp_users
SET
user_pass = MD5('",password,"'),
user_email = '",email,"',
user_nicename = '",nicename,"',
display_name = '",displayname,"'
WHERE user_login = '",username,"';
INSERT INTO exec_results VALUES ('",username,"','",current_schema,"','updated');");
ELSE
SET @expression = CONCAT("INSERT INTO ",current_schema,".wp_users (user_login, user_pass, user_nicename, user_email, user_status, display_name, user_registered) VALUES
('",username,"', MD5('",password,"'), '",nicename,"', '",email,"', '0', '",displayname,"', NOW());
SET @user_insert_id = LAST_INSERT_ID();
INSERT INTO ",current_schema,".wp_usermeta (user_id, meta_key, meta_value) VALUES
(@user_insert_id, 'wp_capabilities', 'a:1:{s:13:\"administrator\";b:1;}');
INSERT INTO ",current_schema,".wp_usermeta (user_id, meta_key, meta_value) VALUES
(@user_insert_id, 'wp_user_level', '10');
INSERT INTO exec_results VALUES ('",username,"','",current_schema,"','added');");
END IF;
PREPARE stmt FROM @expression;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP loopSchemas;
CLOSE wp_schemas;
SELECT * FROM exec_results;
END$$
DELIMITER ;
似乎根本问题在于 MySQL,与 MariaDB 不同,每次执行只需要 ONE 准备语句。
感谢 nbk 帮助分离 if 语句,我能够让它按如下方式工作:
USE mysql;
delimiter $$
DROP PROCEDURE IF EXISTS ensure_global_wp_user $$
CREATE PROCEDURE ensure_global_wp_user(
IN username VARCHAR(255),
IN email VARCHAR(255),
IN password VARCHAR(255),
IN nicename VARCHAR(255),
IN displayname VARCHAR(255)
)
BEGIN
DECLARE wp_schema VARCHAR(255);
DECLARE finished INTEGER DEFAULT 0;
DECLARE wp_schemas CURSOR FOR
SELECT DISTINCT table_schema
FROM INFORMATION_SCHEMA.tables
WHERE table_name = 'wp_users';
DECLARE CONTINUE HANDLER
FOR NOT FOUND
SET finished = 1;
OPEN wp_schemas;
DROP TEMPORARY TABLE IF EXISTS exec_results;
CREATE TEMPORARY TABLE exec_results (
username VARCHAR(255),
dbname VARCHAR(255),
action VARCHAR(255)
);
loopSchemas: LOOP
FETCH wp_schemas INTO wp_schema;
IF finished = 1 THEN
LEAVE loopSchemas;
END IF;
SET @sql = CONCAT("
SELECT EXISTS (
SELECT *
FROM ",wp_schema,".wp_users
WHERE user_login = '",username,"'
) INTO @user_exists;");
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
IF @user_exists = 1 THEN
SET @sql = CONCAT("
UPDATE ",wp_schema,".wp_users
SET
user_pass = MD5('",password,"'),
user_email = '",email,"',
user_nicename = '",nicename,"',
display_name = '",displayname,"'
WHERE user_login = '",username,"';
");
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
INSERT INTO exec_results VALUES (username, wp_schema, 'updated');
ELSE
SET @sql = CONCAT("
INSERT INTO ",wp_schema,".wp_users (user_login, user_pass, user_nicename, user_email, user_status, display_name, user_registered) VALUES
('",username,"', MD5('",password,"'), '",nicename,"', '",email,"', '0', '",displayname,"', NOW());
");
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @user_insert_id = LAST_INSERT_ID();
SET @sql = CONCAT("
INSERT INTO ",wp_schema,".wp_usermeta (user_id, meta_key, meta_value) VALUES
(@user_insert_id, 'wp_capabilities', 'a:1:{s:13:\"administrator\";b:1;}');
");
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @sql = CONCAT("
INSERT INTO ",wp_schema,".wp_usermeta (user_id, meta_key, meta_value) VALUES
(@user_insert_id, 'wp_user_level', '10');
");
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
INSERT INTO exec_results VALUES (username, wp_schema, 'added');
END IF;
END LOOP loopSchemas;
CLOSE wp_schemas;
SELECT * FROM exec_results;
END $$
delimiter ;
我正在尝试编写一个 MySQL 脚本来将管理员用户添加到服务器上的每个 WordPress 数据库并更新用户名中的用户信息已经存在。
我制作了以下脚本,它可以在 MariaDB 10.2.31 和 innodb_version 5.7.29 的服务器上运行,但它不能在 运行 MySQL Community Server 5.7 的服务器上运行.29,我收到一条错误消息:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF EXISTS (SELECT * FROM cpaneluser_wp.wp_users WHERE user_login = 'newwpuser') THEN' at line 1
这是创建存储过程的脚本:
-- Create and update a WordPress administrator across all databases
USE mysql;
delimiter $$
DROP PROCEDURE IF EXISTS ensure_global_wp_user $$
CREATE PROCEDURE ensure_global_wp_user(
IN username VARCHAR(255),
IN email VARCHAR(255),
IN password VARCHAR(255),
IN nicename VARCHAR(255),
IN displayname VARCHAR(255)
)
BEGIN
DECLARE current_schema VARCHAR(255);
DECLARE finished INTEGER DEFAULT 0;
DECLARE wp_schemas CURSOR FOR
SELECT DISTINCT table_schema
FROM INFORMATION_SCHEMA.tables
WHERE table_name = 'wp_users';
DECLARE CONTINUE HANDLER
FOR NOT FOUND
SET finished = 1;
OPEN wp_schemas;
DROP TEMPORARY TABLE IF EXISTS exec_results;
CREATE TEMPORARY TABLE IF NOT EXISTS exec_results (
username VARCHAR(255),
dbname VARCHAR(255),
action VARCHAR(255)
);
loopSchemas: LOOP
FETCH wp_schemas INTO current_schema;
IF finished = 1 THEN
LEAVE loopSchemas;
END IF;
SET @expression = CONCAT("
IF EXISTS (SELECT * FROM ",current_schema,".wp_users WHERE user_login = '",username,"') THEN
UPDATE ",current_schema,".wp_users
SET
user_pass = MD5('",password,"'),
user_email = '",email,"',
user_nicename = '",nicename,"',
display_name = '",displayname,"'
WHERE user_login = '",username,"';
INSERT INTO exec_results VALUES ('",username,"','",current_schema,"','updated');
ELSE
INSERT INTO ",current_schema,".wp_users (user_login, user_pass, user_nicename, user_email, user_status, display_name, user_registered) VALUES
('",username,"', MD5('",password,"'), '",nicename,"', '",email,"', '0', '",displayname,"', NOW());
SET @user_insert_id = LAST_INSERT_ID();
INSERT INTO ",current_schema,".wp_usermeta (user_id, meta_key, meta_value) VALUES
(@user_insert_id, 'wp_capabilities', 'a:1:{s:13:\"administrator\";b:1;}');
INSERT INTO ",current_schema,".wp_usermeta (user_id, meta_key, meta_value) VALUES
(@user_insert_id, 'wp_user_level', '10');
INSERT INTO exec_results VALUES ('",username,"','",current_schema,"','added');
END IF;
");
PREPARE stmt FROM @expression;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP loopSchemas;
CLOSE wp_schemas;
SELECT * FROM exec_results;
END $$
delimiter ;
你可以这样称呼它:
-- Create or update the newwpuser user on all wordpress databases
call ensure_global_wp_user('newwpuser', 'newwpuser@example.com', 'newpassword', 'newwpuser', 'newwpuser');
是否有不同的语法来实现此目的?我也尝试将 sql_mode
设置为 ''
,但没有任何区别。
您的@expression 在mysql.
中没有有效代码试试这个,当然没有你的桌子我无法完全测试它
现在我首先通过另一个准备好的语句确定,如果用户存在,这个 returns 1 表示存在或 0 当 not.this 停在@res.
并使用它确定我应该使用和更新的方式,当存在时或不插入时。
Thbis 应该也可以在 mariadb 中使用。
DROP procedure IF EXISTS `ensure_global_wp_user`;
DELIMITER $$
USE `testdb`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `ensure_global_wp_user`(
IN username VARCHAR(255),
IN email VARCHAR(255),
IN password VARCHAR(255),
IN nicename VARCHAR(255),
IN displayname VARCHAR(255)
)
BEGIN
DECLARE current_schema VARCHAR(255);
DECLARE finished INTEGER DEFAULT 0;
DECLARE wp_schemas CURSOR FOR
SELECT DISTINCT table_schema
FROM INFORMATION_SCHEMA.tables
WHERE table_name = 'wp_users';
DECLARE CONTINUE HANDLER
FOR NOT FOUND
SET finished = 1;
OPEN wp_schemas;
DROP TEMPORARY TABLE IF EXISTS exec_results;
CREATE TEMPORARY TABLE IF NOT EXISTS exec_results (
username VARCHAR(255),
dbname VARCHAR(255),
action VARCHAR(255)
);
loopSchemas: LOOP
FETCH wp_schemas INTO current_schema;
IF finished = 1 THEN
LEAVE loopSchemas;
END IF;
SET @sql = CONCAT("SELECT EXISTS (SELECT * FROM ",current_schema,".wp_users WHERE user_login = '",username,"') INTO @res;");
PREPARE stmt FROM @sql;
EXECUTE stmt;
IF @res = 1 THEN
SET @expression = CONCAT("UPDATE ",current_schema,".wp_users
SET
user_pass = MD5('",password,"'),
user_email = '",email,"',
user_nicename = '",nicename,"',
display_name = '",displayname,"'
WHERE user_login = '",username,"';
INSERT INTO exec_results VALUES ('",username,"','",current_schema,"','updated');");
ELSE
SET @expression = CONCAT("INSERT INTO ",current_schema,".wp_users (user_login, user_pass, user_nicename, user_email, user_status, display_name, user_registered) VALUES
('",username,"', MD5('",password,"'), '",nicename,"', '",email,"', '0', '",displayname,"', NOW());
SET @user_insert_id = LAST_INSERT_ID();
INSERT INTO ",current_schema,".wp_usermeta (user_id, meta_key, meta_value) VALUES
(@user_insert_id, 'wp_capabilities', 'a:1:{s:13:\"administrator\";b:1;}');
INSERT INTO ",current_schema,".wp_usermeta (user_id, meta_key, meta_value) VALUES
(@user_insert_id, 'wp_user_level', '10');
INSERT INTO exec_results VALUES ('",username,"','",current_schema,"','added');");
END IF;
PREPARE stmt FROM @expression;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP loopSchemas;
CLOSE wp_schemas;
SELECT * FROM exec_results;
END$$
DELIMITER ;
似乎根本问题在于 MySQL,与 MariaDB 不同,每次执行只需要 ONE 准备语句。
感谢 nbk 帮助分离 if 语句,我能够让它按如下方式工作:
USE mysql;
delimiter $$
DROP PROCEDURE IF EXISTS ensure_global_wp_user $$
CREATE PROCEDURE ensure_global_wp_user(
IN username VARCHAR(255),
IN email VARCHAR(255),
IN password VARCHAR(255),
IN nicename VARCHAR(255),
IN displayname VARCHAR(255)
)
BEGIN
DECLARE wp_schema VARCHAR(255);
DECLARE finished INTEGER DEFAULT 0;
DECLARE wp_schemas CURSOR FOR
SELECT DISTINCT table_schema
FROM INFORMATION_SCHEMA.tables
WHERE table_name = 'wp_users';
DECLARE CONTINUE HANDLER
FOR NOT FOUND
SET finished = 1;
OPEN wp_schemas;
DROP TEMPORARY TABLE IF EXISTS exec_results;
CREATE TEMPORARY TABLE exec_results (
username VARCHAR(255),
dbname VARCHAR(255),
action VARCHAR(255)
);
loopSchemas: LOOP
FETCH wp_schemas INTO wp_schema;
IF finished = 1 THEN
LEAVE loopSchemas;
END IF;
SET @sql = CONCAT("
SELECT EXISTS (
SELECT *
FROM ",wp_schema,".wp_users
WHERE user_login = '",username,"'
) INTO @user_exists;");
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
IF @user_exists = 1 THEN
SET @sql = CONCAT("
UPDATE ",wp_schema,".wp_users
SET
user_pass = MD5('",password,"'),
user_email = '",email,"',
user_nicename = '",nicename,"',
display_name = '",displayname,"'
WHERE user_login = '",username,"';
");
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
INSERT INTO exec_results VALUES (username, wp_schema, 'updated');
ELSE
SET @sql = CONCAT("
INSERT INTO ",wp_schema,".wp_users (user_login, user_pass, user_nicename, user_email, user_status, display_name, user_registered) VALUES
('",username,"', MD5('",password,"'), '",nicename,"', '",email,"', '0', '",displayname,"', NOW());
");
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @user_insert_id = LAST_INSERT_ID();
SET @sql = CONCAT("
INSERT INTO ",wp_schema,".wp_usermeta (user_id, meta_key, meta_value) VALUES
(@user_insert_id, 'wp_capabilities', 'a:1:{s:13:\"administrator\";b:1;}');
");
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @sql = CONCAT("
INSERT INTO ",wp_schema,".wp_usermeta (user_id, meta_key, meta_value) VALUES
(@user_insert_id, 'wp_user_level', '10');
");
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
INSERT INTO exec_results VALUES (username, wp_schema, 'added');
END IF;
END LOOP loopSchemas;
CLOSE wp_schemas;
SELECT * FROM exec_results;
END $$
delimiter ;