我有一个表在ETL例程期间一次填充一列。 必需列(外键)首先设置,因此表的初始状态为:
key | fkey | a
-------|--------|-------
1 | 1 | null
在处理A值之后,我使用SQL Alchemy和PostgreSQL方言插入它们进行简单的upsert:
upsert = sqlalchemy.sql.text("""
INSERT INTO table
(key, a)
VALUES (:key, :a)
ON CONFLICT (key) DO UPDATE SET
a = EXCLUDED.a
""")
但是这失败了,因为它显然试图将fkey
值插入null
。
psycopg2.IntegrityError: null value in column "fkey" violates not-null constraint
DETAIL: Failing row contains (1, null, 0).
语法是否正确?它为什么失败? SQLAlchemy是否参与此错误或是否正确翻译PLSQL?
我怀疑约束检查是在CONFLICT解决方案触发之前发生的,所以虽然它实际上可行,因为fkey
保证在之前不为空并且不会被覆盖,但约束检查仅查看暂定插入和表约束。
答案 0 :(得分:4)
这是PostgreSQL的current documented limitation,它打破了规范。
目前,此设置仅影响UNIQUE,PRIMARY KEY,REFERENCES(外键)和EXCLUDE约束。 插入或修改行时不会立即检查NOT NULL和CHECK约束(不在语句末尾)。还会立即检查尚未声明为DEFERRABLE的唯一性和排除约束。
您无法推迟NOT NULL
约束,而且您似乎了解默认行为,如此处所示。
CREATE TABLE foo ( a int NOT NULL, b int UNIQUE, c int );
INSERT INTO foo (a,b,c) VALUES (1,2,3);
INSERT INTO foo (b,c) VALUES (2,3);
ERROR: null value in column "a" violates not-null constraint
DETAIL: Failing row contains (null, 2, 3).