从 CSV 文件生成插入 SQL 语句
Posted
技术标签:
【中文标题】从 CSV 文件生成插入 SQL 语句【英文标题】:Generate insert SQL statements from a CSV file 【发布时间】:2010-09-05 17:04:54 【问题描述】:我需要将一个 csv 文件导入到 Firebird 中,我花了几个小时尝试了一些工具,但没有一个适合我的需要。
主要问题是我一直在尝试的所有工具,例如 EMS Data Import 和 Firebird 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)
我该如何处理?
【问题讨论】:
我有时使用The World's Simplest Code Generator (javascript edition)。它是在线的,但它只是 javascript - 您的数据不会去任何地方。不过,还有一个 asp version,具有更多功能。 我在 Balloon 的 Excel technique 上稍作改动。我强烈建议下载免费 ASAP Utilities Excel 插件。它们包括的众多节省时间的工具之一是insert before current value 和insert after current value 选项。这些应该可以让您找到解决方案 非常简单的在线实用程序:Convert from/to CSV 很好,关于十进制类型的一些问题。 更好的转换工具:codebeautify.org/csv-to-sql-converter 【参考方案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 = Full
和DatabaseAccess = 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的,不会上传你的数据(至少在我写这篇的时候没有)
【讨论】:
以上是关于从 CSV 文件生成插入 SQL 语句的主要内容,如果未能解决你的问题,请参考以下文章
从 csv 文件批量插入 - 忽略有错误的行 - SQL Server