Неверный синтаксис хранимой процедуры на MySQL 5.7, но работает на MariaDB - PullRequest
1 голос
/ 25 апреля 2020

Я пытаюсь написать MySQL скрипт для добавления пользователя-администратора в каждую базу данных WordPress на сервере и обновления информации о пользователе в имени пользователя уже существует.

Я сделал следующий скрипт, и он работает на сервере с MariaDB 10.2.31 с innodb_version 5.7.29, но не работает сервер под управлением MySQL Сервер совместной работы 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 на '', но это не имело никакого значения.

Ответы [ 2 ]

2 голосов
/ 28 апреля 2020

Кажется, что фундаментальная проблема заключается в том, что в 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 ;
1 голос
/ 25 апреля 2020

Ваше @ выражение не является допустимым кодом в mysql.

Попробуйте, конечно, без ваших таблиц я не могу проверить это полностью

Теперь сначала я определюсь с помощью другого подготовленного утверждения , если пользователь существует, возвращается 1 для существующего или 0, если нет. Этот парк в @ 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 ;
...