We're Moving!

The Vertica Forum is moving to a new OpenText Analytics Database (Vertica) Community.

Join us there to post discussion topics, learn about

product releases, share tips, access the blog, and much more.

Create My New Community Account Now


MySQL INSERT ... ON DUPLICATE KEY UPDATE - need vertica analogue — Vertica Forum

MySQL INSERT ... ON DUPLICATE KEY UPDATE - need vertica analogue

In MySQL if you trying to insert a record, and it violates unique/primary constraint, it can update existing record.
https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html

Does vertica have anything similar?

Thanks.

Comments

  • Jim_KnicelyJim_Knicely - Select Field - Administrator
    edited October 2017

    No you can't do that in Vertica. Why? That functionality is the result of lazy development.

  • edited October 2017

    So, what is 'not lazy' option?
    I need to save large amount of data to db - fast.
    In Mysql I can group updates to batches, and perform batch in single transatction. And I don't need to check if records in batch violates constraints.

    Any ideas how can I achieve this in vertica would be helpful.
    Thanks.

  • Jim_KnicelyJim_Knicely - Select Field - Administrator

    Primary keys can be enabled or disabled. By default they are disabled. You can change that behavior via the EnableNewPrimaryKeysByDefault database parameter.

    dbadmin=> select current_value, default_value, description from configuration_parameters where parameter_name = 'EnableNewPrimaryKeysByDefault';
     current_value | default_value |                                description
    ---------------+---------------+---------------------------------------------------------------------------
     0             | 0             | Determines whether new primary key constraints will be enabled by default
    (1 row)
    

    Note you can always UPDATE a PK even when a PK is enabled.

    Example:

    dbadmin=> create table update_pk (c1 int not null, c2 varchar(10));
    CREATE TABLE
    
    dbadmin=> alter table update_pk add constraint update_pk_pk primary key (c1);
    ALTER TABLE
    
    dbadmin=> select is_enabled from primary_keys where constraint_name = 'update_pk_pk';
     is_enabled
    ------------
     f
    (1 row)
    
    dbadmin=> insert into update_pk select 1, 'OLD VALUE';
     OUTPUT
    --------
          1
    (1 row)
    
    dbadmin=> update update_pk set c1 = 2, c2 = 'NEW VALUE';
     OUTPUT
    --------
          1
    (1 row)
    
    dbadmin=> select * from update_pk;
     c1 |    c2
    ----+-----------
      2 | NEW VALUE
    (1 row)
    
    dbadmin=> alter table update_pk alter constraint update_pk_pk enabled;
    ALTER TABLE
    
    dbadmin=> update update_pk set c1 = 1, c2 = 'OLD VALUE';
     OUTPUT
    --------
          1
    (1 row)
    
    dbadmin=> select * from update_pk;
     c1 |    c2
    ----+-----------
      1 | OLD VALUE
    (1 row)
    
    dbadmin=> insert into update_pk select 1, 'NEW VALUE';
    ERROR 6745:  Duplicate key values: 'c1=1' -- violates constraint 'public.update_pk.update_pk_pk'
    
    dbadmin=> alter table update_pk alter constraint update_pk_pk disabled;
    ALTER TABLE
    dbadmin=> insert into update_pk select 1, 'NEW VALUE';
     OUTPUT
    --------
          1
    (1 row)
    
    dbadmin=> select * from update_pk;
     c1 |    c2
    ----+-----------
      1 | OLD VALUE
      1 | NEW VALUE
    (2 rows)
    

    Maybe the MERGE command can do what you want?

    Here I UPDATE the matching rows:

    dbadmin=> merge into update_pk using (select 1 c1, 'HMM' c2) foo on foo.c1 = update_pk.c1
    dbadmin-> when matched then update set c1 = foo.c1, c2 = foo.c2
    dbadmin-> when not matched then insert (c1, c2) values (foo.c1, foo.c2);
     OUTPUT
    --------
          2
    (1 row)
    
    dbadmin=> select * from update_pk;
     c1 | c2
    ----+-----
      1 | HMM
      1 | HMM
    (2 rows)
    

    And here I INSERT a new row as there are no matching records:

    dbadmin=> merge into update_pk using (select 2 c1, 'NEW_VALUE' c2) foo on foo.c1 = update_pk.c1
    dbadmin-> when matched then update set c1 = foo.c1, c2 = foo.c2
    dbadmin-> when not matched then insert (c1, c2) values (foo.c1, foo.c2);
     OUTPUT
    --------
          1
    (1 row)
    
    dbadmin=> select * from update_pk;
     c1 |    c2
    ----+-----------
      1 | HMM
      1 | HMM
      2 | NEW_VALUE
    (3 rows)
    
  • Yes, That's what I was looking for!
    Many-many thanks.

  • Jim_KnicelyJim_Knicely - Select Field - Administrator
    edited October 2017

    Cool!

    By the way, I <3 your user name :p

  • I get the following error if i do the same -
    ERROR [42601] ERROR: Subquery in MERGE is not supported;

  • Jim_KnicelyJim_Knicely - Select Field - Administrator
    edited February 2019

    @Deepak_Nailwal - Can you post your SQL statement?

    This works:

    dbadmin=> SELECT version();
                  version
    ------------------------------------
     Vertica Analytic Database v9.2.0-4
    (1 row)
    
    dbadmin=> SELECT * FROM my_merge;
     c1 | c2
    ----+----
      1 | A
    (1 row)
    
    dbadmin=> MERGE INTO my_merge m1 USING (SELECT 2 c1, 'B' c2) m2 ON (m1.c1 = m2.c1)
    dbadmin->   WHEN MATCHED THEN UPDATE SET c2 = m2.c2
    dbadmin->   WHEN NOT MATCHED THEN INSERT (c1, c2) VALUES (m2.c1, m2.c2);
     OUTPUT
    --------
          1
    (1 row)
    
    dbadmin=> SELECT * FROM my_merge;
     c1 | c2
    ----+----
      1 | A
      2 | B
    (2 rows)
    

    See:
    https://www.vertica.com/docs/9.2.x/HTML/Content/Authoring/AdministratorsGuide/Tables/MergeTables/MergeSourceData.htm

  • I'm using Vertica 8.x. Probably it was introduced in Vertica 9.2.

  • Jim_KnicelyJim_Knicely - Select Field - Administrator

    As a work around, create a database view using your subquery...

    Example:

    dbadmin=> SELECT * FROm my_merge;
     c1 | c2
    ----+----
      1 | A
    (1 row)
    
    dbadmin=> SELECT * FROM source;
     c1 | c2
    ----+----
      1 | B
      2 | C
      3 | D
      4 | E
    (4 rows)
    
    dbadmin=> CREATE VIEW source_temp_vw AS SELECT * FROM source WHERE c1 IN (1, 4);
    CREATE VIEW
    
    dbadmin=> SELECT * FROM source_temp_vw;
     c1 | c2
    ----+----
      1 | B
      4 | E
    (2 rows)
    
    dbadmin=> MERGE INTO my_merge m1 USING source_temp_vw m2 ON (m1.c1 = m2.c1)
    dbadmin->  WHEN MATCHED THEN UPDATE SET c2 = m2.c2
    dbadmin->  WHEN NOT MATCHED THEN INSERT (c1, c2) VALUES (m2.c1, m2.c2);
     OUTPUT
    --------
          2
    (1 row)
    
    dbadmin=> SELECT * FROM my_merge;
     c1 | c2
    ----+----
      1 | B
      4 | E
    (2 rows)
    

Leave a Comment

BoldItalicStrikethroughOrdered listUnordered list
Emoji
Image
Align leftAlign centerAlign rightToggle HTML viewToggle full pageToggle lights
Drop image/file