Создание операторов 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)

Решение

Это немного грубо, но для разовых работ я иногда использую 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

вы можете использовать оболочку

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(
...
);

Два онлайн-инструмента, которые помогли мне в 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