如何使用主键和 UNIQUE 列对 table 执行更新插入
How to perform an upsert on a table with both a primary key and UNIQUE column
SQLite 新手,正在尝试了解更新插入功能。
我有一个 table 具有以下 DDL:
CREATE TABLE contacts (
contact_id INTEGER PRIMARY KEY,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE,
phone TEXT NOT NULL UNIQUE
);
假设我插入一条记录:
INSERT INTO contacts (contact_id, first_name, last_name, email, phone)
VALUES (1, 'John', 'Jones', 'jjones@gmail.com', '888-867-5309');
我如何做一个同时考虑 UNIQUE 约束 (email
) 和 PK 约束 (contact_id
) 的更新插入,以便它处理这两种情况,因为我不知道哪个约束将失败。
我试过这样做:
INSERT INTO contacts (contact_id, first_name, last_name, email, phone)
VALUES (1, 'John', 'Jones', 'john.jones@gmail.com', '888-867-5309')
ON CONFLICT (contact_id, email) DO UPDATE
SET first_name='John', last_name='Jones', email='john.jones@gmail.com', phone='888-867-5309'
WHERE contact_id=1;
但我收到错误:
sqlite3.OperationalError: ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint
单独执行它们就可以了。
INSERT INTO contacts (contact_id, first_name, last_name, email, phone)
VALUES (1, 'John', 'Jones', 'john.jones@gmail.com', '888-867-5309')
ON CONFLICT (contact_id) DO UPDATE
SET first_name='John', last_name='Jones', email='john.jones@gmail.com', phone='888-867-5309'
WHERE contact_id=1;
INSERT INTO contacts (contact_id, first_name, last_name, email, phone)
VALUES (1, 'John', 'Jones', 'john.jones@gmail.com', '888-867-5309')
ON CONFLICT (email) DO UPDATE
SET first_name='John', last_name='Jones', email='john.jones@gmail.com', phone='888-867-5309'
WHERE email='john.jones@gmail.com';
我知道我收到错误是因为列的组合不满足单个约束,它包含两个。但是我该如何兼顾两者呢?
因为你定义了:
contact_id INTEGER PRIMARY KEY
contact_id
是 AUTOINCREMENT
并且您必须 而不是 在插入新行时明确为此列设置一个值(尽管 SQLite 不会抱怨如果如果没有冲突,你会这样做)。
所以你只需要:
INSERT INTO contacts (first_name, last_name, email, phone)
VALUES ('John', 'Jones', 'john.jones@gmail.com', '888-867-5309')
ON CONFLICT (email) DO UPDATE
SET first_name='John', last_name='Jones', email='john.jones@gmail.com', phone='888-867-5309';
但是,您还定义了:
phone TEXT NOT NULL UNIQUE
因此您的 table 中有 2 个 UNIQUE
约束。
对于这种情况,如果您希望 SQLite 处理来自两列的冲突,您可以使用 (INSERT OR) REPLACE
:
REPLACE INTO contacts (first_name, last_name, email, phone)
VALUES('Johny', 'Jones', 'john.jones@gmail.com', '888-867-5309')
你必须知道如果没有冲突 REPLACE
插入新行(在你的情况下对于列 email
和 phone
),但是如果有冲突那么删除一个或多个冲突行(因为会有 2 个冲突行,一个用于 email
,另一个用于 phone
)并插入新行。
SQLite 新手,正在尝试了解更新插入功能。
我有一个 table 具有以下 DDL:
CREATE TABLE contacts (
contact_id INTEGER PRIMARY KEY,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE,
phone TEXT NOT NULL UNIQUE
);
假设我插入一条记录:
INSERT INTO contacts (contact_id, first_name, last_name, email, phone)
VALUES (1, 'John', 'Jones', 'jjones@gmail.com', '888-867-5309');
我如何做一个同时考虑 UNIQUE 约束 (email
) 和 PK 约束 (contact_id
) 的更新插入,以便它处理这两种情况,因为我不知道哪个约束将失败。
我试过这样做:
INSERT INTO contacts (contact_id, first_name, last_name, email, phone)
VALUES (1, 'John', 'Jones', 'john.jones@gmail.com', '888-867-5309')
ON CONFLICT (contact_id, email) DO UPDATE
SET first_name='John', last_name='Jones', email='john.jones@gmail.com', phone='888-867-5309'
WHERE contact_id=1;
但我收到错误:
sqlite3.OperationalError: ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint
单独执行它们就可以了。
INSERT INTO contacts (contact_id, first_name, last_name, email, phone)
VALUES (1, 'John', 'Jones', 'john.jones@gmail.com', '888-867-5309')
ON CONFLICT (contact_id) DO UPDATE
SET first_name='John', last_name='Jones', email='john.jones@gmail.com', phone='888-867-5309'
WHERE contact_id=1;
INSERT INTO contacts (contact_id, first_name, last_name, email, phone)
VALUES (1, 'John', 'Jones', 'john.jones@gmail.com', '888-867-5309')
ON CONFLICT (email) DO UPDATE
SET first_name='John', last_name='Jones', email='john.jones@gmail.com', phone='888-867-5309'
WHERE email='john.jones@gmail.com';
我知道我收到错误是因为列的组合不满足单个约束,它包含两个。但是我该如何兼顾两者呢?
因为你定义了:
contact_id INTEGER PRIMARY KEY
contact_id
是 AUTOINCREMENT
并且您必须 而不是 在插入新行时明确为此列设置一个值(尽管 SQLite 不会抱怨如果如果没有冲突,你会这样做)。
所以你只需要:
INSERT INTO contacts (first_name, last_name, email, phone)
VALUES ('John', 'Jones', 'john.jones@gmail.com', '888-867-5309')
ON CONFLICT (email) DO UPDATE
SET first_name='John', last_name='Jones', email='john.jones@gmail.com', phone='888-867-5309';
但是,您还定义了:
phone TEXT NOT NULL UNIQUE
因此您的 table 中有 2 个 UNIQUE
约束。
对于这种情况,如果您希望 SQLite 处理来自两列的冲突,您可以使用 (INSERT OR) REPLACE
:
REPLACE INTO contacts (first_name, last_name, email, phone)
VALUES('Johny', 'Jones', 'john.jones@gmail.com', '888-867-5309')
你必须知道如果没有冲突 REPLACE
插入新行(在你的情况下对于列 email
和 phone
),但是如果有冲突那么删除一个或多个冲突行(因为会有 2 个冲突行,一个用于 email
,另一个用于 phone
)并插入新行。