【问题标题】:Stored procedure, if exists return ID or insert and return ID存储过程,如果存在则返回 ID 或插入并返回 ID
【发布时间】:2019-09-06 22:32:23
【问题描述】:

我有一个非常简单的 DB2 存储过程,我在其中接收一个参数字符串并将其插入到一个表中,它工作正常,但我确实需要扩展它。目前它看起来像这样:

    IN_TAG_DATA


    P1 : BEGIN ATOMIC

    INSERT INTO SCHEMA.TAGS(TAG_DATA)
    VALUES(IN_TAG_DATA);

    END P1

我现在需要做的是放入相同的字符串参数,但基于该参数,我需要检查名称是否已经存在,如果存在则选择/返回它的 id。如果它不存在,我需要插入它,然后返回创建的 ID。

我应该如何改变它以便在此处获得适当的功能?

    IN_TAG_DATA
    OUT_TAG_ID

    P1 : BEGIN ATOMIC

    DECLARE V_TAG_ID INTEGER;

    SELECT CAST(NEXT VALUE FOR SCHEMA . TAG_ID_SEQ AS INTEGER)
    INTO V_TAG_ID
    FROM SYSIBM . SYSDUMMY1;

    /*
    IF EXISTS BASED ON IN_TAG_DATA, GET ID ELSE INSERT AND RETURN created ID
    */


    SET OUT_TAG_ID
    END P1

【问题讨论】:

    标签: sql stored-procedures db2


    【解决方案1】:
    IN_TAG_DATA
    OUT_TAG_ID
    
    P1 : BEGIN ATOMIC
    

    检查TAG ID是否存在于数据库中

    IF EXISTS (SELECT TAG_ID FROM SYSIBM . SYSDUMMY1 WHERE xx = TAG_DATA) 
    THEN
    

    返回标签 ID

    BEGIN
    SET OUT_TAG_ID = TAG_ID
    END;
    ELSE
    

    插入它然后返回创建的ID

    BEGIN
    INSERT INTO SCHEMA.TAGS(TAG_DATA)
    VALUES(IN_TAG_DATA)
    SET OUT_TAG_ID = TAG_ID
    END;
    END IF;
    
    END P1
    

    【讨论】:

    • 谢谢,第一个开始/结束块中到底缺少什么?
    • 因为在第一个块中我想检查 tag_data 是否匹配,然后返回 tag_id
    • 虽然此代码可能会解决问题,including an explanation 关于如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请编辑您的答案以添加解释并说明适用的限制和假设。
    【解决方案2】:
    --#SET TERMINATOR @
    CREATE TABLE TAGS(TAG_ID INT NOT NULL GENERATED ALWAYS AS IDENTITY, TAG_DATA VARCHAR(20) NOT NULL) IN USERSPACE1@
    
    CREATE OR REPLACE PROCEDURE TAGS(P_TAG_DATA VARCHAR(20), OUT P_TAG_ID INT)
    BEGIN
    
    FOR C1 AS 
      WITH E (TAG_ID) AS (
        SELECT TAG_ID
        FROM TAGS
        WHERE TAG_DATA=P_TAG_DATA
      )
      , I AS (
        SELECT TAG_ID
        FROM NEW TABLE (
          INSERT INTO TAGS (TAG_DATA) 
          SELECT P_TAG_DATA FROM TABLE(VALUES 1)
          WHERE NOT EXISTS (SELECT 1 FROM E)
        )
      )
      SELECT COALESCE(E.TAG_ID, I.TAG_ID) TAG_ID
      FROM I FULL JOIN E ON 1=1
    
      DO
        SET P_TAG_ID = C1.TAG_ID;
      END FOR;
    
    END@
    

    有点复杂,但是...
    所有需要的动作都可以通过这个单一的语句来执行。 E 包含一个 TAG_ID 值(如果存在)。仅当新行不存在时才插入新行,并使用 SELECT FROM data-change-table-reference 检索插入的 TAG_ID。最后,我们加入现有行并插入一个。其中只有一个存在,我们得到其中一个TAG_IDs

    如果您使用的是 Db2 for LUW 11.1,则不需要 FOR 循环 - SELECT INTO 语句支持 CTE,因此可以只使用带有 SELECT COALESCE(E.TAG_ID, I.TAG_ID) INTO P_TAG_ID 的单个语句而无需循环。以前的 Db2 版本不支持它,因此,我们必须使用 FOR 循环来检索单个值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-23
      • 2017-02-10
      • 2016-01-18
      相关资源
      最近更新 更多