Создание операторов SQL для вставки из файла CSV
Мне нужно импортировать CSV-файл в Firebird, и я потратил пару часов, пробуя некоторые инструменты, но ни один из них не подходит для моих нужд.
Основная проблема заключается в том, что все инструменты, которые я пробовал, такие как EMS Data Import и Firebird Data Wizard, ожидают, что мой CSV-файл будет содержать всю информацию, необходимую для моей таблицы.
Мне нужно написать некоторый пользовательский SQL в операторе вставки, например, у меня есть файл CSV с названием города, но поскольку в моей базе данных уже есть все города в другой таблице (нормализовано), мне нужно написать подвыбор во вставке оператор для поиска города и записи его идентификатора, а также у меня есть хранимая процедура для создания 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)
Как я могу подойти к этому?
Ответов (12)12
Это немного грубо, но для разовых работ я иногда использую Excel.
Если вы импортируете файл CSV в Excel, вы можете создать формулу, которая создает оператор INSERT, используя конкатенацию строк в формуле. Итак - если ваш CSV-файл имеет 3 столбца, которые появляются в столбцах A, B и C в Excel, вы можете написать формулу вроде ...
="INSERT INTO MyTable (Col1, Col2, Col3) VALUES (" & A1 & ", " & B1 & ", " & C1 & ")"
Затем вы можете реплицировать формулу по всем строкам, скопировать и вставить ответ в текстовый файл для обработки в своей базе данных.
Как я уже сказал - это грубо, но это может быть довольно «быстрый и грязный» способ выполнить работу!
Только что закончил этот сценарий 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
Для этого вы можете использовать бесплатный csvsql .
- Установите его, следуя этим инструкциям
Теперь запустите такую команду, чтобы импортировать ваши данные в вашу базу данных. Более подробная информация по ссылкам выше, но это будет примерно так:
csvsql --db firebase:///d=mydb --insert mydata.csv
Следующее работает с sqlite, и это то, что я использую для преобразования данных в простой для запроса формат.
csvsql --db sqlite:///dump.db --insert mydata.csv
Два онлайн-инструмента, которые помогли мне в 2020 году :
https://numidian.io/convert/csv/to/sql
https://www.convertcsv.com/csv-to-sql.htm
Второй основан на JS и не загружает ваши данные (по крайней мере, в то время, когда я это пишу)
Вы можете импортировать CSV-файл в таблицу как есть, а затем написать SQL-запрос, который выполнит все необходимые преобразования в импортированной таблице и вставит результат в целевую таблицу.
Так что-то вроде:
<(загрузить файл CSV в temp_table - n, city_name)>
вставить в target_table
выберите tn, c.city_id в качестве города
из temp_table t, города c
где t.city_name = c.city_name
Хороший совет по использованию Excel, но я также предлагаю освоиться с языком сценариев, таким как Python, потому что для некоторых задач проще просто написать быстрый скрипт python для выполнения этой работы, чем пытаться найти нужную функцию в Excel или предварительно сделал инструмент, который делает свою работу.
Что ж, если это CSV, и это одноразовый процесс, откройте файл в Excel, а затем напишите формулы для заполнения ваших данных любым желаемым образом, а затем напишите простую формулу Concat для построения вашего SQL, и затем скопируйте эту формулу для каждой строки. Вы получите большое количество операторов SQL, которые можно выполнять где угодно.
Фабио,
Я делал то, что делал Вайбхав много раз, и это хороший «быстрый и грязный» способ получить данные в базе данных.
Если вам нужно сделать это несколько раз или по определенному расписанию, более надежным способом будет загрузить данные 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)
и т.п.
Обычно гораздо быстрее (и надежнее) получить данные В базу данных, а затем исправить данные, чем пытаться исправить данные во время загрузки. Вы также получаете преимущество транзакций, позволяющее ОТКАТИТЬСЯ, если это не сработает !!
Я бы сделал это с помощью 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
для получения дополнительной информации.
Инструмент, который я недавно попробовал, и который отлично зарекомендовал себя, - это FSQL .
Вы пишете команду IMPORT, вставляете ее, FSQL
и она импортирует файл CSV в таблицу Firebird.
вариант 1: 1 - вы пробовали IBExert? IBExpert \ Tools \ Import Data (пробная или клиентская версия).
вариант 2: 2 - загрузите ваш CSV-файл во временную таблицу с помощью F_BLOBLOAD. 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
использовать csv-файл как внешнюю таблицу. Затем вы можете использовать SQL для копирования данных из внешней таблицы в целевую таблицу - со всеми возможностями SQL. См. http://www.firebirdsql.org/index.php?op=useful&id=netzka