【问题标题】:Generate insert SQL statements from a CSV file从 CSV 文件生成插入 SQL 语句
【发布时间】:2010-09-05 17:04:54
【问题描述】:

我需要将一个 csv 文件导入到 Firebird 中,我花了几个小时尝试了一些工具,但没有一个适合我的需要。

主要问题是我一直在尝试的所有工具,例如 EMS Data ImportFirebird Data Wizard,都希望我的 CSV 文件包含我的表格所需的所有信息。

我需要在插入语句中编写一些自定义 SQL,例如,我有一个带有城市名称的 CSV 文件,但是由于我的数据库已经在另一个表中包含所有城市(规范化),我需要编写一个子选择在查找城市并写入其 ID 的插入语句中,我还有一个存储过程来读取 GUIDS。

我的插入语句是这样的:

INSERT INTO PERSON (ID, NAME, CITY_ID) VALUES((SELECT NEW_GUID FROM CREATE_GUID), :NAME, (SELECT CITY_ID FROM CITY WHERE NAME = :CITY_NAME)

我该如何处理?

【问题讨论】:

标签: sql csv insert firebird


【解决方案1】:

好吧,如果它是 CSV,并且这是一个一次性的过程,请在 Excel 中打开文件,然后编写公式以您希望的任何方式填充您的数据,然后编写一个简单的 Concat 公式来构建您的SQL,然后为每一行复制该公式。您将获得大量的 SQL 语句,您可以在任何地方执行这些语句。

【讨论】:

    【解决方案2】:

    这有点粗糙 - 但对于临时工作,我有时会使用 Excel。

    如果您将 CSV 文件导入 Excel,您可以创建一个公式,该公式通过在公式中使用字符串连接来创建一个 INSERT 语句。所以 - 如果您的 CSV 文件有 3 列出现在 Excel 的 A、B 和 C 列中,您可以编写如下公式...

    ="INSERT INTO MyTable (Col1, Col2, Col3) VALUES (" & A1 & ", " & B1 & ", " & C1 & ")"
    

    然后您可以将公式复制到所有行中,然后将答案复制并粘贴到文本文件中以针对您的数据库运行。

    就像我说的 - 它很粗糙 - 但它可能是一种完成工作的“快速而肮脏”的方式!

    【讨论】:

    • 你也可以用一个像样的编辑器(例如vim)打开文件并在每一行应用一个快速宏。
    【解决方案3】:

    您可以将 CSV 文件按原样导入表中,然后编写一个 SQL 查询,对导入的表执行所有必需的转换并将结果插入到目标表中。

    比如:

    插入目标表

    选择 t.n, c.city_id 作为城市

    来自 temp_table t,城市 c

    其中 t.city_name = c.city_name

    关于使用 Excel 的好建议,但我也建议熟悉 Python 之类的脚本语言,因为对于某些任务,编写一个快速的 Python 脚本来完成这项工作比尝试在 Excel 中找到所需的函数或完成这项工作的预制工具。

    【讨论】:

      【解决方案4】:

      法比奥,

      Vaibhav 已经做过很多次了,这是一种很好的“快速而肮脏”的方式将数据导入数据库。

      如果您需要多次执行此操作,或按某种计划执行此操作,那么更可靠的方法是将 CSV 数据“按原样”加载到工作表中(即 customer_dataload),然后使用标准 SQL 语句填充缺失的字段。

      (我不知道 Firebird 的语法 - 但类似...)

      UPDATE person
      SET id = (SELECT newguid() FROM createguid)
      
      UPDATE person
      SET cityid = (SELECT cityid FROM cities WHERE person.cityname = cities.cityname)
      

      等等

      通常,将数据导入数据库然后修复数据比在上传期间尝试修复数据要快得多(也更可靠)。您还可以获得交易的好处,如果它不起作用,您可以回滚!

      【讨论】:

        【解决方案5】:

        我会用awk 来做这个。

        例如,如果您在 CSV 文件中有此信息:

        Bob,New York
        Jane,San Francisco
        Steven,Boston
        Marie,Los Angeles
        

        以下命令将为您提供所需的内容,在与 CSV 文件相同的目录中运行(在此示例中名为 name-city.csv)。

        $ awk -F, '{ print "INSERT INTO PERSON (ID, NAME, CITY_ID) VALUES ((SELECT NEW_GUID FROM CREATE_GUID), '\''"$1"'\'', (SELECT CITY_ID FROM CITY WHERE NAME = '\''"$2"'\''))" }' name-city.csv
        

        输入awk --help了解更多信息。

        【讨论】:

        • 这非常无益。花几秒钟的时间制作一个快速而肮脏的例子可以为不知道如何使用 awk 的人节省几个小时。
        【解决方案6】:

        我最近尝试过的一个非常好用的工具是FSQL

        您编写一个 IMPORT 命令,将其粘贴到 FSQL 中,然后它将 CSV 文件导入 Firebird 表中。

        【讨论】:

          【解决方案7】:

          刚刚完成了这个 VBA 脚本,它可能对这个目的很方便。所需要做的就是更改 Insert 语句以包含相关表和列列表(显然它们在 Excel 文件中出现的顺序相同)。

          Function CreateInsertStatement()
              'Output file location and start of the insert statement
              SQLScript = "C:\Inserts.sql"
              cStart = "Insert Into Holidays (HOLIDAY_ID, NAT_HOLDAY_DESC, NAT_HOLDAY_DTE) Values ("
          
              'Open file for output
              Open SQLScript For Output As #1
          
              Dim LoopThruRows As Boolean
              Dim LoopThruCols As Boolean
          
          
              nCommit = 1 'Commit Count
              nCommitCount = 100 'The number of rows after which a commit is performed
          
              LoopThruRows = True
              nRow = 1 'Current row
          
              While LoopThruRows
          
                  nRow = nRow + 1 'Start at second row - presuming there are headers
                  nCol = 1 'Reset the columns
                  If Cells(nRow, nCol).Value = Empty Then
                      Print #1, "Commit;"
                      LoopThruRows = False
                  Else
                      If nCommit = nCommitCount Then
                          Print #1, "Commit;"
                          nCommit = 1
                      Else
                          nCommit = nCommit + 1
                      End If
          
                      cLine = cStart
                      LoopThruCols = True
          
                      While LoopThruCols
                          If Cells(nRow, nCol).Value = Empty Then
                              cLine = cLine & ");"                    'Close the SQL statement
                              Print #1, cLine                         'Write the line
                              LoopThruCols = False                    'Exit the cols loop
                          Else
                              If nCol > 1 Then                        'add a preceeding comma for all bar the first column
                                  cLine = cLine & ", "
                              End If
                              If Right(Left(Cells(nRow, nCol).Value, 3), 1) = "/" Then 'Format for dates
                                  cLine = cLine & "TO_DATE('" & Cells(nRow, nCol).Value & "', 'dd/mm/yyyy')"
                              ElseIf IsNumeric(Left(Cells(nRow, nCol).Value, 1)) Then 'Format for numbers
                                  cLine = cLine & Cells(nRow, nCol).Value
                              Else 'Format for text, including apostrophes
                                  cLine = cLine & "'" & Replace(Cells(nRow, nCol).Value, "'", "''") & "'"
                              End If
          
                              nCol = nCol + 1
                          End If
                      Wend
                  End If
              Wend
          
              Close #1
          
          End Function
          

          【讨论】:

            【解决方案8】:

            选项 1: 1-您尝试过 IBExert 吗? IBExpert \ Tools \ Import Data(试用版或客户版)。

            选项 2: 2- 使用 F_BLOBLOAD 将您的 csv 文件上传到临时表。 3- 创建一个存储过程,它使用了 3 个函数(f_stringlength、f_strcopy、f_MID) 你跨过所有的弦,拉动你的领域来构建你的 INSERT INTO。

            链接: 2:http://freeadhocudf.org/documentation_english/dok_eng_file.html 3:http://freeadhocudf.org/documentation_english/dok_eng_string.html

            【讨论】:

              【解决方案9】:

              将 csv 文件用作外部表。然后,您可以使用 SQL 将数据从外部表复制到目标表 - 使用 SQL 的所有可能性。 见http://www.firebirdsql.org/index.php?op=useful&id=netzka

              【讨论】:

              • +1 用于提及外部表,但请注意,您需要将数据在定长记录和字段中作为CHAR(n),并且您需要GRANT 的权限,并且您需要允许使用ExternalFileAccess = FullDatabaseAccess = Full 访问firebird.conf 中的文件。
              【解决方案10】:

              您可以使用免费的csvsql 来执行此操作。

              • 安装它using these instructions
              • 现在运行类似的命令将数据导入数据库。上面的链接中的更多详细信息,但它会是这样的:

                csvsql --db firebase:///d=mydb --insert mydata.csv

              • 以下适用于 sqlite,是我用来将数据转换为易于查询的格式

                csvsql --db sqlite:///dump.db --insert mydata.csv

              【讨论】:

                【解决方案11】:

                你可以使用外壳

                sed "s/,/','/g" file.csv > tmp
                sed "s/$/'),(/g" tmp > tmp2
                sed "s/^./'&/g" tmp2 > insert.sql
                

                然后添加

                INSERT INTO PERSON (ID, NAME, CITY_ID) VALUES(
                ...
                );
                

                【讨论】:

                  【解决方案12】:

                  2020 帮助我的两个在线工具:

                  https://numidian.io/convert/csv/to/sql

                  https://www.convertcsv.com/csv-to-sql.htm

                  第二个是基于JS的,不会上传你的数据(至少在我写这篇的时候没有)

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-11-03
                    • 1970-01-01
                    • 2018-12-08
                    • 1970-01-01
                    • 2013-09-26
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多