我如何使用 sqlite3 删除约束?

how do i drop constraint with sqlite3?

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

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";
  `,
);

我的错误:

改变 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 支持的唯一 DROP 语句是:-

  • 下降指数
  • 删除TABLE
  • 掉落扳机
  • 删除视图

ALTER TABLE 语句相对受限:-

因此,您需要重新创建 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(all occurences)提取 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;

结果:-

原始数据table

Extra - 替换 SQL 示例,其中删除了 UNQIUE

Extra - 按照原始 table

的列信息

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

SQL 用于新的 table(还显示 UNIQUE 列的索引已被删除)

替换的列table

// 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');