下面是一段将 json 数组解析为数据库中的表的小代码:
CREATE TEMPORARY TABLE json_import (doc json) ON COMMIT DROP;
INSERT INTO json_import (doc) VALUES(
'[
{
"cli_nk": 1,
"effective_from_date": "2021-01-18",
"effective_to_date": "",
"user_dml_type_code": "U",
"user_fix_desc": "qwert"
},
{
"cli_nk": 2,
"effective_from_date": "2023-03-25",
"effective_to_date": "",
"user_dml_type_code": "I",
"user_fix_desc": "qwe"
},
{
"cli_nk": 4,
"effective_from_date": "2015-07-18",
"effective_to_date": "2999-12-31",
"user_dml_type_code": "D",
"user_fix_desc": "ytrewq"
},
{
"cli_nk": 5,
"effective_from_date": "2016-08-03",
"effective_to_date": "2999-12-31",
"user_dml_type_code": "U",
"user_fix_desc": "zxc"
}
]'
);
INSERT INTO user_type (cli_nk, effective_from_date, effective_to_date, user_dml_type_code, user_fix_desc)
SELECT
NULLIF (p.cli_nk, ''),
NULLIF (p.effective_from_date, ''),
NULLIF (p.effective_to_date, ''),
NULLIF (p.user_dml_type_code, ''),
NULLIF (p.user_fix_desc, '')
FROM json_import l
CROSS JOIN LATERAL json_populate_recordset(NULL::user_type, doc) AS p;
我的 user_type 表的 DDL:
CREATE TABLE public.user_type (
cli_nk text NULL,
effective_from_date date NULL,
effective_to_date date NULL,
user_dml_type_code bpchar(1) NOT NULL,
user_fix_desc text NULL
);
但是当我尝试执行它后,出现以下错误:
SQL 错误 [22007]:错误:日期类型语法无效:“” 位置:180
如何处理此错误并正确填写表格?
NULLIF 返回用作输入的数据类型,在您的情况下为 TEXT。您必须将结果从 NULLIF 转换为所需的数据类型,在您的情况下为 DATE:
INSERT INTO user_type (cli_nk, effective_from_date, effective_to_date, user_dml_type_code, user_fix_desc)
SELECT
NULLIF (p.cli_nk, ''),
CAST(NULLIF (p.effective_from_date, '') AS date),
CAST(NULLIF (p.effective_to_date, '') AS date),
NULLIF (p.user_dml_type_code, ''),
NULLIF (p.user_fix_desc, '')
FROM json_import l
CROSS JOIN LATERAL json_populate_recordset(NULL::user_type, doc) AS p;
您的问题与 json 中包含的某些日期未指定(等于空字符串)有关。当 Postgres 在 INSERT 语句期间尝试将空字符串转换为 DATE 数据类型时,不知道如何处理它,因为空字符串不是空值。
解决这个问题的一种方法是定义一个临时数据类型,它可以 获取空字符串作为字符串,然后将原始数据类型转换为表的数据类型。
CREATE TYPE raw_data AS (
cli_nk INTEGER,
effective_from_date TEXT,
effective_to_date TEXT,
user_dml_type_code TEXT,
user_fix_desc TEXT
);
INSERT INTO user_type
SELECT cli_nk,
CAST(CASE WHEN NOT effective_from_date = '' THEN effective_from_date END AS DATE),
CAST(CASE WHEN NOT effective_to_date = '' THEN effective_to_date END AS DATE),
user_dml_type_code,
user_fix_desc
FROM json_import l
CROSS JOIN LATERAL JSON_POPULATE_RECORDSET(NULL::raw_data, l.doc) AS p;
输出:
cli_nk | 生效日期 | 有效日期 | 用户_dml_类型_代码 | 用户修复_描述 |
---|---|---|---|---|
1 | 2021-01-18T00:00:00.000Z | 空 | 你 | qwert |
2 | 2023-03-25T00:00:00.000Z | 空 | 我 | qwe |
4 | 2015-07-18T00:00:00.000Z | 2999-12-31T00:00:00.000Z | D | ytrewq |
5 | 2016-08-03T00:00:00.000Z | 2999-12-31T00:00:00.000Z | 你 | zxc |
查看演示这里。