当 Count(*) = 0 时,IBM DB2 INSERT

IBM DB2 INSERT when Count(*) = 0

我们的开发数据库每周重置一次。我发现自己在周一早上(比如今天)花了一个小时左右的时间将我所有的测试数据从各个脚本插入到各种表和数据库中。

首先,当然,我要确认这些表中没有我的数据:

SELECT Count(*) FROM Table1 WHERE INVLINK LIKE '190701050630%'

如果没有返回行,我可以插入我的记录:

INSERT INTO Table1
(       UPC,    CATALOG, VENDOR,  ADD_DATE, INVLINK, WHO_ADDED, TYPE, VENDOR_ID)
VALUES
('011010017760', 'LOVE', 'TES', '20150609', '19070105063041', 9388, 'P', '1013'),
('011010017760', 'HATE', 'TES', '20150609', '19070105063042', 9388, 'P', '1013'),
('011010017760', 'FEAR', 'TES', '20150609', '19070105063043', 9388, 'P', '1013')

我想知道是否有一种语法允许我在计数为零时调用插入命令。

这是我试过的方法,但这不会通过 SQL 调用执行

SELECT CASE WHEN SELECT Count(*) = 0
THEN 
INSERT INTO TBLBARTRANS
(       UPC,    CATALOG, VENDOR,  ADD_DATE, INVLINK, WHO_ADDED, TYPE, VENDOR_ID)
VALUES
('011010017760', 'LOVE', 'TES', '20150609', '19070105063041', 9388, 'P', '1013'),
('011010017760', 'HATE', 'TES', '20150609', '19070105063042', 9388, 'P', '1013'),
('011010017760', 'FEAR', 'TES', '20150609', '19070105063043', 9388, 'P', '1013')
END
FROM Table1 
WHERE INVLINK LIKE '190701050630%'

我可以调用 INSERT、SELECT 和 UPDATE 命令,但我不是数据库管理员。因此,为 运行 这 15 到 20 个脚本创建存储过程对我来说不是一个选择。

您没有说明您使用的是哪个 DB2 版本和平台,但是 MERGE 语句很可能就是您要查找的内容。 MERGE is documented here.

您可以指定搜索条件,insert/update 取决于结果。根据您的要求,您只需要插入、更新、select...

的权限

您需要更改它,以便您只 "select" 那些不存在的值:

INSERT INTO TBLBARTRANS
 (UPC, CATALOG, VENDOR, ADD_DATE, INVLINK, WHO_ADDED, TYPE, VENDOR_ID)
select *
from (
  values 
    ('011010017760', 'LOVE', 'TES', '20150609', '19070105063041', 9388, 'P', '1013'),
   ('011010017760', 'HATE', 'TES', '20150609', '19070105063042', 9388, 'P', '1013'),
   ('011010017760', 'FEAR', 'TES', '20150609', '19070105063043', 9388, 'P', '1013')
) as t (UPC, CATALOG, VENDOR, ADD_DATE, INVLINK, WHO_ADDED, TYPE, VENDOR_ID)
where not exists (select 1 
                  from TBLBARTRANS tbl
                  where tbl.invlink = t.invlink);

最里面的 select 创建一个 "virtual" table,其中包含您要插入的值:

select *
from (
  values 
    ('011010017760', 'LOVE', 'TES', '20150609', '19070105063041', 9388, 'P', '1013'),
    ('011010017760', 'HATE', 'TES', '20150609', '19070105063042', 9388, 'P', '1013'),
    ('011010017760', 'FEAR', 'TES', '20150609', '19070105063043', 9388, 'P', '1013')
) as t(UPC, CATALOG, VENDOR, ADD_DATE, INVLINK, WHO_ADDED, TYPE, VENDOR_ID)

上面只是 "simulates" 一个来源 table 用于您要插入的值。条件

where not exists (select 1 
                  from TBLBARTRANS tbl
                  where tbl.invlink = t.invlink);

将仅 return "virtual" table 中尚不存在于 table TBLBARTRANS 中的那些行。然后 select 语句的结果将被插入到目标 table 中。

我在 DB2 LUW 上对此进行了测试 - 不确定 所有 DB2 版本是否支持我使用的 values() 子句。


Henrik 建议的 DB2 的 MERGE 是一个替代方案:

merge into TBLBARTRANS tg
using table (
  values 
    ('011010017760', 'LOVE', 'TES', '20150609', '19070105063041', 9388, 'P', '1013'),
    ('011010017760', 'HATE', 'TES', '20150609', '19070105063042', 9388, 'P', '1013'),
    ('011010017760', 'FEAR', 'TES', '20150609', '19070105063043', 9388, 'P', '1013')
) t (UPC, CATALOG, VENDOR,  ADD_DATE, INVLINK, WHO_ADDED, TYPE, VENDOR_ID) on (t.INVLINK = tg.invlink)
when not matched then 
  insert (UPC, CATALOG, VENDOR, ADD_DATE, INVLINK, WHO_ADDED, TYPE, VENDOR_ID)
  values (t.UPC, t.CATALOG, t.VENDOR, t.ADD_DATE, t.INVLINK, t.WHO_ADDED, t.TYPE, t.VENDOR_ID);

无关,但是:

add_datedate 还是 varchar 列?如果它是 varchar 列,那么您应该更改它。将日期存储为字符串几乎总是一个非常糟糕的主意。

VENDOR_ID 也是如此:您向看起来非常像数字的那一列提供字符串值。在 varchar 列中存储数字也几乎总是一个非常糟糕的主意。

除了其他人所说的之外,您还可以考虑将数据移动到 csv 文件和 load/ingest 文件,而不是将它们插入 sql 语句中。

https://www-01.ibm.com/support/knowledgecenter/SSEPGG_10.1.0/com.ibm.db2.luw.admin.cmd.doc/doc/r0057198.html?cp=SSEPGG_10.1.0%2F3-6-2-4-59

https://www-01.ibm.com/support/knowledgecenter/SSEPGG_10.1.0/com.ibm.db2.luw.admin.cmd.doc/doc/r0008305.html?cp=SSEPGG_10.1.0%2F3-6-2-4-83

加载将拒绝那些违反主键的行,并加载其余行。 Ingest 为您提供更多控制权,您甚至可以使用如上所述的合并语句。

即使您不想使用这些实用程序中的任何一个,您也可能需要考虑将数据与实际命令分开。例如,您可以创建一个实用程序脚本,该脚本循环遍历多个 table,读取 table 的数据文件并动态构造插入语句。所有需要的信息都在目录中。

编辑:

还有一个想法是创建备份 table,其中包含您要添加到真实 table 的数据。我假设重置意味着备份已恢复。如果备份包含备份 table,您可以每周一从这些 table 插入、合并、从游标加载。缺点是当数据发生变化时,你必须重新备份。