在 INSERT 语句中解析 json 时,日期数据类型不匹配

问题描述 投票:0回答:2

下面是一段将 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

如何处理此错误并正确填写表格?

sql json postgresql date sql-insert
2个回答
0
投票

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;

0
投票

您的问题与 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

查看演示这里

© www.soinside.com 2019 - 2024. All rights reserved.