【问题标题】:Vertica sql overwrite data on insertVertica sql在插入时覆盖数据
【发布时间】:2020-08-13 07:28:38
【问题描述】:

vertica中每次有insert语句如何覆盖表?

考虑:

INSERT INTO table1 VALUES ('My Value');

这会给你说

| MyCol  |
----------
MyValue

如何在下一个插入语句中覆盖同一个表

INSERT INTO table1 VALUES ('My Value2');

| MyCol  |
----------
MyValue2

【问题讨论】:

    标签: sql vertica vsql


    【解决方案1】:

    您可以DELETETRUNCATE 您的餐桌。 Vertica 没有覆盖方法。使用TRUNCATE,因为您只想要一个值。

    Source

    INSERT INTO table1 VALUES ('My Value');
    TRUNCATE TABLE table1;
    INSERT INTO table1 VALUES ('My Value2'); 
    

    或者(如果在提交之前连接丢失,则不会生效。)

    Rollback

    单个语句返回错误消息。在这种情况下,Vertica 会回滚该语句。

    DDL 错误、系统故障、死锁和资源限制会返回 ROLLBACK 消息。在这种情况下,Vertica 会回滚整个事务。

    INSERT INTO table1 VALUES ('My Value');
    DELETE FROM table1
    WHERE MyCol !='My Value2';
    INSERT INTO table1 VALUES ('My Value2'); 
    COMMIT;
    

    【讨论】:

    • 好的,所以 vertica 不为其提供覆盖?但这里的问题是在截断之后,如果连接断开,然后您不必插入说,并且想要以前的值,那么它不会是一个问题
    • 在这种情况下检查或请。 @超自然
    【解决方案2】:

    我可能会建议你不要这样做。

    最简单的方法是用一行填充表格,也许:

    insert into table1 (value)
        values (null);
    

    然后使用update,而不是insert

    update table1
        set value = ?;
    

    这解决了你的问题。

    如果您坚持使用insert,您可以插入带有标识列的值并使用视图获取最新值:

    create table table1 (
        table1_id identity(1, 1),
        value varchar(255)
    );
    

    然后使用视图访问表:

    create view v_table1 as
        select value
        from table1
        order by table1_id desc
        limit 1;
    

    如果视图变得低效,您可以定期清空表格。

    这种方法的一个优点是表永远不会为空,也不会长时间锁定——因此它通常是可用的。在这方面删除行和插入行可能会很棘手。

    如果你真的喜欢触发器,你可以使用上面的表格。然后使用触发器更新 another 表中只有一行的行。这也最大限度地提高了可用性,而无需获取最新值的开销。

    【讨论】:

      【解决方案3】:

      如果它是一个单行表,那么按照 @Gordon Linoff 的建议,用可以为 NULL 的单行填充它没有任何风险。

      在内部,您应该知道 Vertica 在后台始终将 UPDATE 实现为 DELETE,方法是为行添加删除向量,然后应用 INSERT。

      单行表没问题,作为 Tuple Mover(后台守护进程唤醒所有 5 分钟以对内部存储进行碎片整理,简单地说,将创建单个数据(读取优化存储- ROS) container out of: 前一个值;指向该前一个值的删除向量,从而将其停用,以及它更新到的新插入的值。 所以:

      CREATE TABLE table1 (
        mycol VARCHAR(16)
      ) UNSEGMENTED ALL NODES; -- a small table, replicate it across all nodes
      -- now you have an empty table
      -- for the following scenario, I assume you commit the changes every time, as other connected
      -- processes will want to see the data you changed
      -- then, only once:
      INSERT INTO table1 VALUES(NULL::VARCHAR(16);
      -- now, you get a ROS container for one row.
      -- Later:
      UPDATE table1 SET mycol='first value';
      -- a DELETE vector is created to mark the initial "NULL" value as invalid
      -- a new row is added to the ROS container with the value "first value"
      -- Then, before 5 minutes have elapsed, you go:
      UPDATE table1 SET mycol='second value';
      -- another DELETE vector is created, in a new delete-vector-ROS-container, 
      -- to mark "first value" as invalid
      -- another new row is added to a new ROS container, containing "second value"
      -- Now 5 minutes have elapsed since the start, the Tuple Mover sees there's work to do,
      -- and:
      -- - it reads the ROS containers containing "NULL" and "first value"
      -- - it reads the delete-vector-ROS containers marking both "NULL" and "first value"
      --    as invalid
      -- - it reads the last ROS container containing "second value"
      -- --> and it finally merges all into a brand new ROS container, to only contain.
      --     "second value", and, at the end the four other ROS containers are deleted.
      

      对于单行表,这非常有效。不要对十亿行这样做。

      【讨论】:

        猜你喜欢
        • 2019-01-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-30
        • 2014-11-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多