【问题标题】:Insert into a Informix table or update if exists插入 Informix 表或更新(如果存在)
【发布时间】:2016-08-23 09:07:50
【问题描述】:

我想向 Informix 数据库表中添加一行,但是当存在具有相同唯一键的行时,我想更新该行。

我找到了 MySQL here 的解决方案,如下所示,但 Informix 需要它:

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE name="A", age=19

【问题讨论】:

    标签: sql informix


    【解决方案1】:

    您可能应该使用MERGE 语句。

    给定一个合适的table

    create table table (id serial not null primary key, name varchar(20) not null, age integer not null);
    

    此 SQL 有效:

    MERGE INTO table AS dst
        USING (SELECT 1 AS id, 'A' AS name, 19 AS age
                 FROM sysmaster:'informix'.sysdual
              ) AS src
        ON dst.id = src.id
        WHEN NOT MATCHED THEN INSERT (dst.id, dst.name, dst.age)
             VALUES (src.id, src.name, src.age)
        WHEN MATCHED THEN UPDATE SET dst.name = src.name, dst.age = src.age
    

    Informix 有一些有趣的规则,允许在不需要双引号的情况下使用关键字作为标识符(事实上,除非您在环境中设置了 DELIMIDENT,否则双引号只是字符串周围单引号的替代方案)。

    【讨论】:

    • 很棒的解决方案;但是,如果我要插入/更新的值之一为 null,则 Informix 11.7 会在使用“null AS columnName”时生成系统错误。您可以通过使用“nvl(null, null) as columnName”来解决这个问题。我还必须使用 FROM sysmaster:informix.sysdual (informix 周围没有引号)
    • 我目前无法测试,但尝试使用 NULL::INTEGER(使用列的类型)。如果这不起作用,我将不得不进行实验。
    • 如果源表中的行违反了目标表中的唯一索引(例如,具有重复的 id),Informix 数据库仍然会抱怨并抛出错误。与INSERT ... ON DUPLICATE KEY UPDATE ... 相差甚远。
    【解决方案2】:

    您可以使用MERGE 语句尝试相同的行为:

    示例,创建目标表:

    CREATE TABLE target 
    (
        id      SERIAL PRIMARY KEY CONSTRAINT pk_tst,
        name    CHAR(1),
        age     SMALLINT
    );
    

    创建一个临时源表,插入你想要的记录:

    CREATE TEMP TABLE source
    (
        id      INT,
        name    CHAR(1),
        age     SMALLINT
    ) WITH NO LOG;
    
    INSERT INTO source (id, name, age) VALUES (1, 'A', 19);
    

    合并将是:

    MERGE INTO target AS t 
    USING source AS s ON t.id = s.id
    
    WHEN MATCHED THEN 
        UPDATE
        SET t.name = s.name, t.age = s.age
    
    WHEN NOT MATCHED THEN 
        INSERT (id, name, age) 
        VALUES (s.id, s.name, s.age);
    

    您会看到记录已插入,然后您可以:

    UPDATE  source
    SET     age = 20
    WHERE   id = 1;
    

    然后再次测试 MERGE。

    另一种方法是创建一个存储过程,基本上你会做INSERT语句并检查SQL错误代码,如果是-100你去UPDATE

    类似:

    CREATE PROCEDURE sp_insrt_target(v_id INT, v_name CHAR(1), v_age SMALLINT)
        ON EXCEPTION IN (-100)
            UPDATE target
            SET name = v_name, age = v_age
            WHERE id = v_id;
        END EXCEPTION
        INSERT INTO target VALUES (v_id, v_name, v_age);
    END PROCEDURE;
    

    【讨论】:

    • MERGE 甚至不接近 INSERT ... ON DUPLICATED KEY UPDATE ...。在上面的示例中,只需在源表中添加具有重复 id 的另一行,例如INSERT INTO source (id, name, age) VALUES (1, 'A', 19); INSERT INTO source (id, name, age) VALUES (1, 'B', 20); 再试一次。 Informix 数据库会抱怨Could not insert new row - duplicate value in a UNIQUE INDEX column
    • 是的@Rockallite 有一些规则和限制。现在,那里有一个实际的问题吗?好像您正在追逐另一个测试用例,在这种情况下是迁移。您能否更具体地说明目标、使用的版本……但这应该是另一个问题。
    猜你喜欢
    • 2011-05-11
    • 2020-04-04
    • 1970-01-01
    相关资源
    最近更新 更多