Как выполнить массовую вставку из CSV, если некоторые поля имеют символ новой строки? - PullRequest
4 голосов
/ 25 марта 2010

У меня есть дамп CSV из другой БД, который выглядит следующим образом (идентификатор, имя, примечания):

1001, Джон Смит, 15 Main Street
1002, Джейн Смит, "2010 Rockliffe Dr.
Плезантвиль, Иллинойс
США "
1003, Bill Karr, 2820 West Ave.

Последнее поле может содержать возврат каретки и запятые, в этом случае оно заключено в двойные кавычки. И мне нужно сохранить эти возвраты и запятые.

Я использую этот код для импорта CSV в мою таблицу:

BULK INSERT CSVTest
FROM 'c:\csvfile.csv'
WITH
(
  FIELDTERMINATOR = ',',
  ROWTERMINATOR = '\n'
)

SQL Server 2005 массовая вставка не может определить, что возврат каретки внутри кавычек не является ограничителем строки .
Как побороть?


UPDATE
Похоже, что единственный способ сохранить разрывы строк внутри поля - это использовать другой разделитель строк. Итак, я хочу отметить все разрывы строк, разделяющих строки, поставив перед ними трубу. Как я могу изменить свой CSV, чтобы выглядеть так?

1001, Джон Смит, 15 Main Street |
1002, Джейн Смит, "2010 Rockliffe Dr.
Плезантвиль, Иллинойс
США "|
1003, Билл Карр, 2820 West Ave. |

Ответы [ 6 ]

1 голос
/ 25 марта 2010

вы можете поменять эти разрывы строк в одну строку с помощью скрипта, например, вы можете использовать GNU sed для удаления разрывов строк. например,

$ more file
1001,John Smith,15 Main Street
1002,Jane Smith,"2010 Rockliffe Dr.
Pleasantville, IL
USA"
1003,Bill Karr,"2820
West Ave"

$ sed '/"/!s/$/|/;/.*\".*[^"]$/{ :a;N };/"$/ { s/$/|/ }' file
1001,John Smith,15 Main Street|
1002,Jane Smith,"2010 Rockliffe Dr.
Pleasantville, IL
USA"|
1003,Bill Karr,"2820
West Ave"|

тогда вы можете массово вставить.

Редактировать:

Сохраните это: /"/!s/$/|/;/.*\".*[^"]$/{ :a;N };/"$/ { s/$/|/ } в файле, скажем myformat.sed. затем сделайте это в командной строке

c:\test> sed.exe -f myformat.sed myfile

1 голос
/ 25 марта 2010

Массовые операции на SQL Server специально не поддерживают CSV, даже если они могут импортировать их, если файлы тщательно отформатированы.Мое предложение заключалось бы в том, чтобы заключить все значения полей в кавычки.BULK INSERT может затем разрешить возврат каретки в пределах значения поля.Если это не так, то вашим следующим решением может быть пакет служб Integration Services.

Подробнее см. Подготовка данных для массового экспорта или импорта .

0 голосов
/ 26 марта 2010

Хорошо, вот небольшая Java-программа, которую я в итоге пишу для решения проблемы.
Комментарии, исправления и оптимизации приветствуются.

import java.io.*;

public class PreBulkInsert
{
    public static void main(String[] args)
    {
        if (args.length < 3)
        {
            System.out.println ("Usage:");
            System.out.println ("  java PreBulkInsert input_file output_file separator_character");
            System.exit(0);
        }

        try
        {
            boolean firstQuoteFound = false;
            int fromIndex;
            int lineCounter = 0;
            String str;

            BufferedReader in = new BufferedReader(new FileReader(args[0]));
            BufferedWriter out = new BufferedWriter(new FileWriter(args[1])); 
            String newRowSeparator = args[2];

            while ((str = in.readLine()) != null)
            {
                fromIndex = -1;
                do
                {
                    fromIndex = str.indexOf('"', fromIndex + 1);
                    if (fromIndex > -1)
                        firstQuoteFound = !firstQuoteFound;
                } while (fromIndex > -1);

                if (!firstQuoteFound)
                    out.write(str + newRowSeparator + "\r\n");
                else
                    out.write(str + "\r\n");
                lineCounter++;
            }
            out.close();
            in.close();
            System.out.println("Done! Total of " + lineCounter + " lines were processed.");
        }
        catch (IOException e)
        {
            System.out.println(e.getMessage());
            System.exit(1);
        }       
    }
}
0 голосов
/ 25 марта 2010

Если у вас есть контроль над содержимым CSV-файла, вы можете заменить разрывы строк в поле (CRLF) символом без перевода строки (возможно, просто CR или LF), а затем запустить скрипт после импорта, чтобы заменить их на CRLF снова.

Вот как продукты MS Office (Excel, Access) решают эту проблему.

0 голосов
/ 25 марта 2010

Вы не можете импортировать это, если CSV находится в допустимом формате. Таким образом, вы должны либо исправить дамп, либо вручную с помощью поиска и замены исправить нежелательные символы новой строки.

0 голосов
/ 25 марта 2010

Согласно источнику всех знаний (Википедия), csv использует новые строки для разделения записей. Так что то, что у вас есть, не является действительным CSV.

Я предлагаю написать Perl-программу для обработки вашего файла и добавить каждую запись в базу данных.

Если вы не являетесь perl-человеком, вы можете зайти на сайт программирования или посмотреть, будет ли какой-то добрый человек писать раздел разбора программы для вас.

Добавлено:

Возможное решение

Поскольку ОП заявляет, что он может изменить входной файл, я бы изменил все новые строки, которые не следуют за «, на зарезервированную последовательность символов, например XXX

Это может быть автоматическая замена во многих редакторах. В Windows UltraEdit включает функцию поиска / замены регулярных выражений

Затем импортируйте в базу данных, так как у вас больше не будет встроенных новых строк.

Затем используйте SQL Замените , чтобы преобразовать вхождения XXX обратно в новые строки.

...