我在“kladr_full_name”列中有sql错误空值违反了非空约束。
执行请求的数据库中的表:
СREATE TABLE kladr.kladr_name
(
kladr_code character varying(255) NOT NULL,
kladr_city_name character varying(121),
kladr_full_name character varying(487) NOT NULL,
kladr_index character varying(6),
kladr_name character varying(100) NOT NULL,
kladr_naspunkt_name character varying(121),
kladr_rayon_name character varying(121),
kladr_region_name character varying(121),
kladr_socr character varying(20),
CONSTRAINT kladr_name_pkey PRIMARY KEY (kladr_code )
)
WITH (
OIDS=FALSE
);
ALTER TABLE kladr.kladr_name
OWNER TO postgres;
请求db:
INSERT INTO kladr.kladr_name
(kladr_code,
kladr_name,
kladr_socr,
kladr_index,
kladr_region_name,
kladr_rayon_name,
kladr_city_name,
kladr_naspunkt_name,
kladr_full_name)
SELECT kladr_code,
Upper(kladr_name) kladr_name,
kladr_socr,
kladr_index,
(SELECT k1.kladr_socr
||' '
||k1.kladr_name
FROM kladr.kladr_tmp k1
WHERE k1.kladr_region = k.kladr_region
AND k1.kladr_rayon = '000'
AND k1.kladr_city = '000'
AND k1.kladr_nas_punkt = '000'
AND k1.kladr_mod = '00'
AND k1.kladr_status = '0')kladr_region_name,
(SELECT k1.kladr_socr
||' '
||k1.kladr_name
FROM kladr.kladr_tmp k1
WHERE k1.kladr_region = k.kladr_region
AND k1.kladr_rayon = k.kladr_rayon
AND k1.kladr_rayon <> '000'
AND k1.kladr_city = '000'
AND k1.kladr_nas_punkt = '000'
AND k1.kladr_name = '00') kladr_rayon_name,
(SELECT k1.kladr_socr
||' '
||k1.kladr_name
FROM kladr.kladr_tmp k1
WHERE k1.kladr_region = k.kladr_region
AND k1.kladr_rayon = k.kladr_rayon
AND k1.kladr_city = k.kladr_city
AND k1.kladr_city <> '000'
AND k1.kladr_nas_punkt = '000'
AND k1.kladr_mod = '00') kladr_city_name,
(SELECT k1.kladr_socr
||' '
||k1.kladr_name
FROM kladr.kladr_tmp k1
WHERE k1.kladr_region = k.kladr_region
AND k1.kladr_rayon = k.kladr_rayon
AND k1.kladr_city = k.kladr_city
AND k1.kladr_nas_punkt = k.kladr_nas_punkt
AND k1.kladr_nas_punkt <> '000'
AND k1.kladr_mod = '00') kladr_naspunkt_name,
(SELECT k1.kladr_socr
||' '
||k1.kladr_name
FROM kladr.kladr_tmp k1
WHERE k1.kladr_region = k.kladr_region
AND k1.kladr_rayon = '000'
AND k1.kladr_city = '000'
AND k1.kladr_nas_punkt = '000'
AND k1.kladr_mod = '00'
AND k1.kladr_status = '0')
||' '
||(SELECT k1.kladr_socr
||' '
||k1.kladr_name
FROM kladr.kladr_tmp k1
WHERE k1.kladr_region = k.kladr_region
AND k1.kladr_rayon = k.kladr_rayon
AND k1.kladr_rayon <> '000'
AND k1.kladr_city = '000'
AND k1.kladr_nas_punkt = '000'
AND k1.kladr_mod = '00')
||' '
||(SELECT k1.kladr_socr
||' '
||k1.kladr_name
FROM kladr.kladr_tmp k1
WHERE k1.kladr_region = k.kladr_region
AND k1.kladr_rayon = k.kladr_rayon
AND k1.kladr_city = k.kladr_city
AND k1.kladr_city <> '000'
AND k1.kladr_nas_punkt = '000'
AND k1.kladr_mod = '00')
||' '
||(SELECT k1.kladr_socr
||' '
||k1.kladr_name
FROM kladr.kladr_tmp k1
WHERE k1.kladr_region = k.kladr_region
AND k1.kladr_rayon = k.kladr_rayon
AND k1.kladr_city = k.kladr_city
AND k1.kladr_nas_punkt = k.kladr_nas_punkt
AND k1.kladr_nas_punkt <> '000'
AND k1.kladr_mod = '00')kladr_full_name
FROM kladr.kladr_tmp k
WHERE k.kladr_mod = '00'
DB postgreSql。 jpa prov hibernate。这可能是什么原因?
现在问题是如果修改此查询以在postgres中工作(在oracle db中工作之前),如果某些subquerys返回null?
答案 0 :(得分:3)
在PostgreSQL中,如果a || b
中的任何一个参数为NULL
,则NULL
形式的表达式将计算为INSERT
。因此,如果这些子查询中的任何无法找到记录,则您的NULL
语句会尝试将kladr_full_name
插入NULL
。您需要分别尝试每个子查询,看看哪一个没有给你一个记录(或者给你一个NULL
的记录。)
编辑添加以响应OP评论:在Oracle中,没有零长度字符串的概念,因为它们已转换为'' = ''
(例如,{{} 1}}不是真的,而'' IS NULL
是)。通常转换是单向的 - LENGTH('') IS NULL
- 但在||
运算符的情况下,它会将NULL
转换回零长度字符串,这样'ab' || NULL || 'cd'
就是'abcd'
。 PostgreSQL不会自动执行此转换,因为它 区分''
与NULL
,但您可以:
COALESCE
函数明确执行此转换(§9.17 "Conditional Expressions" of the PostgreSQL 9.2 Manual中记录):COALESCE(NULL, '')
评估为''
;或CONCAT
函数(记录在§9.4 "String Functions and Operators" of the PostgreSQL 9.2 Manual中)而不是||
运算符。 CONCAT
函数只会跳过任何NULL
个参数,因此CONCAT('ab', NULL, 'cd')
的计算结果为'abcd'
。但是,此功能仅在PostgreSQL 9.x中可用,因此如果您使用的是PostgreSQL 8.x或更早版本,则需要使用COALESCE
方法。