如果表不存在或不是重复行,则插入到Vertica中

时间:2015-10-20 23:28:09

标签: python pandas insert vertica

我编写了一个python脚本来使用create table if not exists语句创建表,然后将数据帧中的行插入到vertica数据库中。我第一次运行这个python脚本时,我希望它创建一个表并插入数据 - 它工作正常。

但是从下一次开始,我希望它只有在不存在时才能创建表(工作正常),并且只有在数据库中不包含该行时才插入数据。

我使用insert语句和COPY语句来插入数据。如何在python中执行此操作?我使用pyodbc从python访问Vertica数据库。

编辑帖子以包含一些代码: 有一个名为tableframe_df的数据框,我需要将内容填充到如下所示的表中:

我正在使用create table创建一个表,如果不存在,则创建一个表(如果没有表)。

  cursor.execute("create table if not exists <tablename>  (fields in the table)")

COPY statement to write to this table from a csv that was created 
`cursor.execute("COPY tablename1 FROM LOCAL 'tablename.csv' DELIMITER ',' exceptions 'exceptions' rejected data 'rejected'")`

##for i,row in tablename_df.iterrows():
       cursor.execute("insert into tablename2 values(?,?,?,?,?,?,?,?,?,?,?,?)",row.values[0],row.values[1],row.values[2],row.values[3],row.values[4],row.values[5],row.values[6],row.values[7],row.values[8],row.values[9],row.values[10],row.values[11])

在上面的代码中,我正在创建表,然后使用COPY和insert插入tablename1和tablename2。这在第一次执行时工作正常(因为表中没有数据)。现在错误地说,如果我运行两次相同的脚本,数据将在这些表中插入两次。 如果数据已经存在,我应该执行哪些检查以确保数据不会被插入?

1 个答案:

答案 0 :(得分:1)

首先我要提一下,如果你要做很多行,INSERT VALUES会很慢。如果您正在使用批处理sql和标准vertica驱动程序,它应该将其转换为COPY,但如果没有,那么您的插入可能需要永久。我不认为pyodbc会发生这种情况,因为它们没有最佳地实现executemany()。您可以使用ceodbc,但我还没有尝试过。或者,您可以使用具有vertica_python命令效率的.copy('COPY FROM STDIN...',data)

无论如何,对于你的问题......

你可以通过以下两种方式之一做到这一点。同样对于插入,我真的会尝试将其更改为副本或至少executemany。同样,pydobc不能正确地执行此操作,至少对于我使用的版本而言。

  1. 使用一个控制表,以某种方式唯一地描述正在加载的数据集并插入其中,并在运行脚本之前检查数据集是否尚未加载。

    - 步骤1.检查控制表的数据集负载。

    SELECT *
    FROM   mycontroltable
    WHERE  dataset = ?
    

    - 步骤2.如果找不到行,请插入行

    for row in data:
        cursor.execute('INSERT INTO mytargettable....VALUES(...)')
    

    - 步骤3.将行插入控制表

    INSERT INTO mycontroltable( dataset ) VALUES ( ? )
    

    - 步骤4.提交数据

    COMMIT
    
  2. 或者,您可以根据键插入或合并数据。您可以创建临时表或其他临时表来执行此操作。如果您不想更新并且数据一旦插入就不会更改,那么INSERT会更好,因为它不会产生删除向量。我会INSERT根据你提出的问题的方式做。{/ p>

    - 步骤1.为中间目标创建本地临时值

    CREATE LOCAL TEMP TABLE mytemp (fields) ON COMMIT DELETE ROWS;
    

    - 步骤2.插入数据。

    for row in data: 
        cursor.execute('INSERT INTO mytemp....VALUES(...)')
    

    - 步骤3.仅按键值插入/选择不存在的数据

    INSERT INTO mytargettable (fields)
    SELECT fields
    FROM mytemp 
    WHERE NOT EXISTS (
        SELECT 1  
        FROM   mytargettable t
        WHERE  t.key = mytemp.key
    )
    

    - 步骤4.提交

    COMMIT;