Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使用csv文件中的“插入到表中”值避免重复_Sql_Sql Server_Pyodbc - Fatal编程技术网

Sql 使用csv文件中的“插入到表中”值避免重复

Sql 使用csv文件中的“插入到表中”值避免重复,sql,sql-server,pyodbc,Sql,Sql Server,Pyodbc,我有一个.csv文件,有6亿多行。我需要把这个上传到数据库。它将有3列被指定为主键 我使用pandas以1000行为单位读取文件 在每次块迭代中,我使用 INSERT INTO db_name.dbo.table_name("col1", "col2", "col3", "col4") VALUES (?,?,?,?) cursor.executemany(query, df.values.tolist()) 使用python中的pyodbc语法,以1000行为单位上传数据 不幸的是,显

我有一个
.csv
文件,有6亿多行。我需要把这个上传到数据库。它将有3列被指定为主键

我使用
pandas
以1000行为单位读取文件

在每次块迭代中,我使用

INSERT INTO db_name.dbo.table_name("col1", "col2", "col3", "col4")
VALUES (?,?,?,?)

cursor.executemany(query, df.values.tolist())  
使用python中的
pyodbc
语法,以1000行为单位上传数据

不幸的是,显然存在一些重复的行。当遇到重复行时,由于SQL Server出错,上载将停止

问题:我如何上传数据,使得每当遇到重复数据而不是停止时,它都会跳过该行并上传其余数据?我在或上找到了一些问题和答案,但在读取文件和使用
insert into table col_names values()
命令时没有找到任何问题和答案

基于这些答案,一个想法可能是:

在块的每次迭代中:

  • 上传到临时表
  • 执行从临时表到最终表的插入
  • 删除临时表中的行
  • 然而,由于每秒都有这么大的文件,我一直在寻找效率更高的答案

    我还尝试使用python处理重复文件,但是,由于文件太大,无法放入内存,我找不到方法来处理

    问题2:如果我使用
    批量插入
    ,我将如何实现跳过重复项


    谢谢

    您可以尝试使用CTE和
    插入。。。选择。。。不存在的地方

    WITH cte
    AS
    (
    SELECT ? col1,
           ? col2,
           ? col3,
           ? col4
    )
    INSERT INTO db_name.dbo.table_name
                (col1,
                 col2,
                 col3,
                 col4)
                SELECT col1,
                       col2,
                       col3,
                       col4
                       FROM cte
                       WHERE NOT EXISTS (SELECT *
                                                FROM db_name.dbo.table_name
                                                WHERE table_name.col1 = cte.col1
                                                      AND table_name.col2 = cte.col2
                                                      AND table_name.col3 = cte.col3
                                                      AND table_name.col4 = cte.col4);
    

    如果列不是主键的一部分,可能会删除一些
    表\u name.col=cte.col

    我总是先加载到临时加载表中,该表对这些列没有任何唯一或PK约束。通过这种方式,您可以始终看到整个文件已加载,这对于任何ETL工作以及对源数据的任何其他简单分析来说都是非常宝贵的检查

    然后使用前面答案中建议的插入,或者如果您知道目标表为空,则只需

    INSERT INTO db_name.dbo.table_name(col1,col2,col3,col4)
    SELECT distinct col1,col2,col3,col4 from load_table
    

    最好的方法是使用临时表并执行MERGE-INSERT语句。您可以这样做(未经测试):


    您需要考虑临时表的最佳索引,以使<强>合并<>强>更快。SQL Server Integration Services提供了一种方法,可以从源中读取数据(通过数据流任务),然后使用其排序控件(用于删除重复项的复选框)删除重复项,这取决于on子句

    当然,必须对数据进行排序,而且6000多万行不会太快


    如果要使用纯SQL Server,则需要一个临时表(没有pk约束)。将数据导入Staging后,您将使用复合PK组合的筛选将数据插入到目标表中。比如说,

    Insert into dbo.RealTable (KeyCol1, KeyCol2, KeyCol3, Col4) 
    Select Col1, Col2, Col3, Col4 
      from dbo.Staging S 
     where not exists (Select *
                         from dbo.RealTable RT 
                        where RT.KeyCol1 = S.Col1
                          AND RT.KeyCol2 = S.Col2
                          AND RT.KeyCol3 = S.Col3
                      )
    
    理论上,您也可以使用set运算符,除非它从两个表中获取不同的值。例如:

    INSERT INTO RealTable
    SELECT * FROM Staging
    EXCEPT
    SELECT * FROM RealTable
    

    将从Staging中插入不同的行到RealTable中(RealTable中不存在)。此方法不考虑在多行上使用不同值的组合PK,因此插入错误将指示在csv中为同一PK组合键分配不同的值。

    从csv文件读取的要插入的值在哪里?@ilyas:在Python客户端中,就像在当前代码中一样(当然,除了嵌入的查询字符串之外,Python代码不需要为此进行更改。)当我应用代码时,会出现以下错误:
    SystemError:返回一个带有错误集的结果
    
    INSERT INTO RealTable
    SELECT * FROM Staging
    EXCEPT
    SELECT * FROM RealTable