【问题标题】:how do i drop constraint with sqlite3?我如何用 sqlite3 放弃约束?
【发布时间】:2020-04-21 07:42:30
【问题描述】:

如果存在这个约束,我会尝试删除一个约束,但我得到一个错误,这是我的代码,在错误下方:

return knex.schema.raw(
  `
    ALTER TABLE users
    DROP CONSTRAINT IF EXISTS "users_customer_id_email_unique",
    DROP CONSTRAINT IF EXISTS "users_customer_id_trigram_unique";
  `,
);

我的错误:

ALTER TABLE 用户

          DROP CONSTRAINT IF EXISTS "users_customer_id_email_unique",
          DROP CONSTRAINT IF EXISTS "users_customer_id_trigram_unique";
         - SQLITE_ERROR: near "DROP": syntax errorError: SQLITE_ERROR: near "DROP": syntax error

【问题讨论】:

标签: sqlite syntax unique-constraint


【解决方案1】:

SQLite 支持的唯一 DROP 语句是:-

  • 删除索引
  • 删除表
  • 删除触发器
  • 下拉视图

ALTER TABLE 语句相对有限:-

因此,您需要重新创建表格,减少约束。

以下可能是这样做的基础:-

CREATE TABLE IF NOT EXISTS new_users (users_customer_id_email_unique TEXT,users_customer_id_trigram_unique INTEGER, othercolumn);
INSERT INTO new_users SELECT * FROM users;
DROP TABLE IF EXISTS old_users;
ALTER TABLE users RENAME TO old_users; /* could be dropped instead of altered but safer to alter then drop */
ALTER TABLE new_users RENAME TO users;
DROP TABLE IF EXISTS old_users; 

工作示例

也许可以根据您的代码考虑以下示例。请注意,这还包括一些可能有用的附加功能,例如提取删除了 UNIQUE(所有出现)的 sql。

DROP TABLE IF EXISTS old_users;
DROP TABLE IF EXISTS users;
CREATE TABLE IF NOT EXISTS users (users_customer_id_email_unique TEXT UNIQUE,users_customer_id_trigram_unique INTEGER UNIQUE, othercolumn);
INSERT INTO users VALUES ('a@email.com',1,'blah'),('b@email.com',2,'blah'),('c@email.com',3,'blah');
/* try to addd some duplicate data (will not be added) */
INSERT OR IGNORE INTO users VALUES ('a@email.com',1,'blah'),('b@email.com',2,'blah'),('c@email.com',3,'blah');
/*RESULT 1 - data in table before removing unique constraint */
SELECT * FROM users;

/* Potentially useful extras that could be used in generating SQL for new table */
SELECT replace(replace(sql,' UNIQUE',''),' unique','') AS newsql FROM sqlite_master WHERE name = 'users';
SELECT * FROM pragma_table_info('users');

/* The actual constraint removal using hard coded replacement table */
CREATE TABLE IF NOT EXISTS new_users (users_customer_id_email_unique TEXT,users_customer_id_trigram_unique INTEGER, othercolumn);
INSERT INTO new_users SELECT * FROM users; /* populate the replacement table */
DROP TABLE IF EXISTS old_users; /* just in case */
ALTER TABLE users RENAME TO old_users; /* could DROP the table here instead of ALTER and subsequent DROP */
ALTER TABLE new_users RENAME TO users;
DROP TABLE IF EXISTS old_users;
/* Add some duplicate rows */
INSERT OR IGNORE INTO users VALUES ('a@email.com',1,'blah'),('b@email.com',2,'blah'),('c@email.com',3,'blah');

/* END RESULTS */
SELECT * FROM users;
SELECT * FROM sqlite_master WHERE name = 'users' OR tbl_name = 'users';
SELECT * FROM pragma_table_info('users');

/* Cleanup Testing Environment */
DROP TABLE IF EXISTS users;

结果:-

原表中的数据

Extra - 删除 UNQIUE 的替换 SQL 示例

额外 - 原始表格中的列信息

修改后的表格数据(添加了重复数据)

新表的 SQL(也显示 UNIQUE 列的索引已被删除)

替换表的列

【讨论】:

    【解决方案2】:
    // we first autorise schema modification
    await knex.raw('PRAGMA writable_schema = true');
    // then drop unique email_customer_id
    await knex
      .select()
      .table('sqlite_master')
      .where('type', '=', 'index')
      .andWhere('tbl_name', '=', 'users')
      .andWhere('name', '=', 'users_email_customer_id_unique')
      .del();
    
    //and also drop unique customer_id_trigram
    await knex
      .select()
      .table('sqlite_master')
      .where('type', '=', 'index')
      .andWhere('tbl_name', '=', 'users')
      .andWhere('name', '=', 'users_customer_id_trigram_unique')
      .del();
    
    // I move back the autorisation for schema modification to false
    return knex.raw('PRAGMA writable_schema = false');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-20
      • 2011-08-01
      • 2013-03-04
      • 1970-01-01
      • 2021-06-29
      • 2016-05-26
      • 2019-07-10
      相关资源
      最近更新 更多