web-dev-qa-db-ja.com

存在する場合にのみ外部キーを削除します

MySQLデータベースを使用しています。

私はこれをやっていますが、うまくいきません。

ALTER TABLE `object` DROP FOREIGN KEY IF EXISTS `object_ibfk_1`;

可能であれば、このIF EXISTSを配置しようとしました。ドロップする前に外部キーが存在するかどうかを確認するにはどうすればよいですか?

25
Creditto

外部キーが存在し、プロシージャを使用したくないの場合、外部キーを削除する場合は、この方法で実行できます(MySQLの場合):

set @var=if((SELECT true FROM information_schema.TABLE_CONSTRAINTS WHERE
            CONSTRAINT_SCHEMA = DATABASE() AND
            TABLE_NAME        = 'table_name' AND
            CONSTRAINT_NAME   = 'fk_name' AND
            CONSTRAINT_TYPE   = 'FOREIGN KEY') = true,'ALTER TABLE table_name
            drop foreign key fk_name','select 1');

prepare stmt from @var;
execute stmt;
deallocate prepare stmt;

外部キーがある場合、変数にalter tableステートメントを配置し、ない場合はダミーステートメントを配置します。そして、それを実行します。

23
NikolaB

再利用性を高めるには、実際にストアドプロシージャを使用する必要があります。目的のDBでこのコードを1回実行します。

   DROP PROCEDURE IF EXISTS PROC_DROP_FOREIGN_KEY;
    DELIMITER $$
    CREATE PROCEDURE PROC_DROP_FOREIGN_KEY(IN tableName VARCHAR(64), IN constraintName VARCHAR(64))
    BEGIN
        IF EXISTS(
            SELECT * FROM information_schema.table_constraints
            WHERE 
                table_schema    = DATABASE()     AND
                table_name      = tableName      AND
                constraint_name = constraintName AND
                constraint_type = 'FOREIGN KEY')
        THEN
            SET @query = CONCAT('ALTER TABLE ', tableName, ' DROP FOREIGN KEY ', constraintName, ';');
            PREPARE stmt FROM @query; 
            EXECUTE stmt; 
            DEALLOCATE PREPARE stmt; 
        END IF; 
    END$$
    DELIMITER ;

その後、いつでもこれを置き換えることができます。

ALTER TABLE `object` DROP FOREIGN KEY IF EXISTS `object_ibfk_1`;

これとともに:

CALL PROC_DROP_FOREIGN_KEY('object', 'object_ibfk_1');

スクリプトは、object_ibfk_1は実際に存在するかどうか。

多くのクレジット: http://simpcode.blogspot.com.ng/2015/03/mysql-drop-foreign-key-if-exists.html

12
Ifedi Okonkwo
IF EXISTS(
              SELECT *
              FROM INFORMATION_SCHEMA.STATISTICS
              WHERE INDEX_SCHEMA = DATABASE()
                    AND TABLE_NAME='myTable'
                    AND INDEX_NAME = 'myIndex')
        THEN

            ALTER TABLE `myTable` DROP FOREIGN KEY `myForeignKey`;

            ALTER TABLE `myTable` DROP INDEX `myIndex` ;

        END IF;

外部キー制約を作成すると、mysqlは参照列にインデックスを自動的に作成します。上記の例は、INFORMATION_SCHEMAでインデックスをチェックする方法を示していますが、 情報スキーマ でチェックアウトするためのより多くの情報があります。インデックス名は、FK用に作成されたことを示しているようです。そのため、最初にFKを削除してから、インデックスを削除する必要があります。外部キーを再度作成すると、mysqlはインデックスを再度作成します。テーブルスキャンを行わずに参照整合性を適用するには、インデックスが必要です。

同じ列を含む新しいインデックスを作成する場合は、最初にそのインデックスを作成する必要があります(この列では、FKとして使用されるインデックスが、インデックス)。これでFKを追加し直すことができ、mysqlは別のインデックスを作成せずに新しいインデックスを使用できるようになります。

編集:インデックスをすばやく表示するには、SHOW INDEXES FROM myTableを実行するだけです。

11
heruka

Mariadb 10.1.26(新しいMysql)の現在のバージョンでは、クエリは機能します。

キー:MUL

ALTER TABLE `object` DROP FOREIGN KEY IF EXISTS `object_ibfk_1`;
DESC `object`;

キー:<NULL>

1
IntCom

どのデータベースを使用していますか??

SQL Serverの場合

if exists (select 1 from sys.objects where object_id = OBJECT_ID(N'[FKName]') AND      
parent_object_id = OBJECT_ID('TableName'))
alter table TableName drop constraint FKName
1
Jack Daniel's

DROP FOREIGN KEY IF EXISTSの前のMySQLおよびMariaDBバージョンにはないv10.1.4の回避策を次に示します。 FOREIGN KEYの存在に依存する必要がある他のすべてのステートメントにも使用できます(たとえば、以下の例のようにSELECT "info: foreign key exists."の場合)。

-- DROP FOREIGN KEY IF EXISTS
SELECT
    COUNT(*)
INTO
    @FOREIGN_KEY_my_foreign_key_ON_TABLE_my_table_EXISTS
FROM
    `information_schema`.`table_constraints`
WHERE
    `table_schema` = 'my_database'
    AND `table_name` = 'my_table'
    AND `constraint_name` = 'my_foreign_key'
    AND `constraint_type` = 'FOREIGN KEY'
;
-- SELECT @FOREIGN_KEY_my_foreign_key_ON_TABLE_my_table_EXISTS;
SET @statement := IF(
    @FOREIGN_KEY_my_foreign_key_ON_TABLE_my_table_EXISTS > 0,
    -- 'SELECT "info: foreign key exists."',
    'ALTER TABLE my_table DROP FOREIGN KEY my_foreign_key',
    'SELECT "info: foreign key does not exist."'
);
PREPARE statement FROM @statement;
EXECUTE statement;
1
automatix