【问题标题】:Delete all foreign keys in mysql database删除mysql数据库中的所有外键
【发布时间】:2015-06-03 11:13:35
【问题描述】:

我可以看到有一些问题 [1,2] 已经提出了这个问题,但是解决方案没有包含完整的 SQL 脚本来完成这个任务。 我有一种情况,仅使用 SQL 删除所有外键会非常有帮助。 目前我正在尝试使用存储过程和游标来解决这个问题,如下所示:

-- No automatic commits:
DROP PROCEDURE IF EXISTS removeConstraints;
-- Magic to happen soon:
DELIMITER |
CREATE PROCEDURE removeConstraints()
BEGIN
  SET AUTOCOMMIT=0;
  SET FOREIGN_KEY_CHECKS=0;
  -- https://dev.mysql.com/doc/refman/5.0/en/cursors.html
  -- https://stackoverflow.com/questions/1745165/looping-over-result-sets-in-mysql
  -- https://mariadb.com/kb/en/mariadb/cursor-overview/
  DECLARE done INT DEFAULT FALSE;
  DECLARE s VARCHAR(1024) DEFAULT '';
  DECLARE cur CURSOR FOR SELECT CONCAT('ALTER TABLE ',TABLE_NAME, ' DROP FOREIGN KEY ', CONSTRAINT_NAME, ';')
    FROM INFORMATION_SCHEMA.Key_COLUMN_USAGE
    WHERE REFERENCED_TABLE_NAME IS NOT NULL;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur;

  read_loop: LOOP
    FETCH cur INTO s;
    IF done THEN
      LEAVE read_loop;
    END IF;
    PREPARE stmt FROM @s;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
  END LOOP;

  CLOSE cur;

  SET FOREIGN_KEY_CHECKS=1;
  COMMIT;
  SET AUTOCOMMIT=1;
END |
DELIMITER ;
-- Do magic:
CALL removeConstraints();
-- Cleanup:
DROP PROCEDURE removeConstraints;

遗憾的是,这会产生以下错误消息:

ERROR 1064 (42000) at line 5: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'DECLARE done INT DEFAULT FALSE;
  DECLARE s VARCHAR(1024) DEFAULT '';
  DECLARE ' at line 8

使用来自Ravinder Reddy 的输入,我现在更新了BEGIN 之后的DECLARE 部分,如下所示:

CREATE PROCEDURE removeConstraints()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE s VARCHAR(1024) DEFAULT '';
  DECLARE cur CURSOR FOR 
          SELECT DISTINCT CONCAT('ALTER TABLE ',TABLE_NAME,' DROP FOREIGN KEY ',CONSTRAINT_NAME,';')
          FROM INFORMATION_SCHEMA.Key_COLUMN_USAGE
          WHERE TABLE_SCHEMA=DATABASE()
          AND REFERENCED_TABLE_NAME IS NOT NULL;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  SET AUTOCOMMIT=0;
  SET FOREIGN_KEY_CHECKS=0;

但是当我尝试执行该过程时,我仍然收到错误:

  MariaDB [v4]> CALL removeConstraints();
  ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NULL' at line 1

我也尝试过使用不同的SELECT 语句,例如:

SELECT CONCAT('ALTER TABLE ',TABLE_NAME,' DROP FOREIGN KEY ',CONSTRAINT_NAME,';')
FROM INFORMATION_SCHEMA.Key_COLUMN_USAGE
WHERE TABLE_SCHEMA=DATABASE()
AND CONSTRAINT_NAME != 'PRIMARY'
AND CONSTRAINT_NAME IS NOT NULL
AND TABLE_NAME IS NOT NULL;

……但它没有帮助。


我现在通过更改代码让它工作,以便稍后发生CONCAT

DROP PROCEDURE IF EXISTS removeConstraints;
-- Magic to happen soon:
DELIMITER |
CREATE PROCEDURE removeConstraints()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE tName VARCHAR(64);
  DECLARE cName VARCHAR(64);
  DECLARE cur CURSOR FOR 
          SELECT DISTINCT TABLE_NAME, CONSTRAINT_NAME
          FROM INFORMATION_SCHEMA.Key_COLUMN_USAGE
          WHERE TABLE_SCHEMA=DATABASE()
          AND REFERENCED_TABLE_NAME IS NOT NULL;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  SET AUTOCOMMIT=0;
  SET FOREIGN_KEY_CHECKS=0;

  OPEN cur;

  read_loop: LOOP
    FETCH cur INTO tName, cName;
    IF done THEN
      LEAVE read_loop;
    END IF;
    SET @sql = CONCAT('ALTER TABLE ',tName,' DROP FOREIGN KEY ',cName,';');
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
  END LOOP;

  CLOSE cur;

  SET FOREIGN_KEY_CHECKS=1;
  COMMIT;
  SET AUTOCOMMIT=1;
END |
DELIMITER ;
-- Do magic:
CALL removeConstraints();
-- Cleanup:
DROP PROCEDURE removeConstraints;

【问题讨论】:

  • 好的,我的印象是它可能与PREPARE 声明有关。因为如果我使用 PREPARE stmt FROM 'SELECT "TEST";'; 一切顺利 o.O
  • near 'NULL' 问题可能是由于从未设置过@s

标签: mysql sql mariadb


【解决方案1】:

所有DECLARE 语句必须位于BEGIN - END 块的顶部。

所有其他陈述都应遵循它们。

在您的代码中,您在 DECLARE 语句之前定义了 SET 语句。
将这些语句移至DECLARE 语句的下方。

示例

  -- https://dev.mysql.com/doc/refman/5.0/en/cursors.html
  -- https://stackoverflow.com/questions/1745165/looping-over-result-sets-in-mysql
  -- https://mariadb.com/kb/en/mariadb/cursor-overview/
  DECLARE done INT DEFAULT FALSE;
  DECLARE s VARCHAR(1024) DEFAULT '';
  DECLARE cur CURSOR FOR 
          SELECT CONCAT('ALTER TABLE ',TABLE_NAME,' DROP FOREIGN KEY ',CONSTRAINT_NAME,';')
            FROM INFORMATION_SCHEMA.Key_COLUMN_USAGE
           WHERE REFERENCED_TABLE_NAME IS NOT NULL;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  SET AUTOCOMMIT=0;
  SET FOREIGN_KEY_CHECKS=0;

文档参考

DECLARE Syntax

DECLARE 只允许在 BEGIN ... END 复合语句中 并且必须在它的开头,在任何其他语句之前。

声明必须遵循一定的顺序。游标声明必须 出现在处理程序声明之前。变量和条件 声明必须出现在游标或处理程序声明之前

【讨论】:

  • 感谢您的回答!我的印象是它已经在某种程度上帮助了我,但不是全部。另外我觉得我处理调试有点笨拙……
猜你喜欢
  • 2013-01-10
  • 1970-01-01
  • 2014-04-13
  • 2020-06-23
  • 1970-01-01
  • 2018-01-15
  • 1970-01-01
  • 2014-02-09
  • 1970-01-01
相关资源
最近更新 更多