Массовая вставка, SQL Server 2000, переносы строк Unix - PullRequest
34 голосов
/ 26 января 2009

Я пытаюсь вставить файл .csv в базу данных с переводом строки Unix. Я запускаю команду:

BULK INSERT table_name
FROM 'C:\file.csv' 
WITH 
( 
    FIELDTERMINATOR = ',', 
    ROWTERMINATOR = '\n' 
) 

Если я преобразовываю файл в формат Windows, загрузка работает, но я не хочу делать этот дополнительный шаг, если его можно избежать. Есть идеи?

Ответы [ 8 ]

98 голосов
/ 17 ноября 2010

Я чувствовал себя обязанным внести свой вклад, поскольку у меня возникла та же проблема, и мне нужно читать 2 файла UNIX из SAP, по крайней мере, пару раз в день. Поэтому вместо использования unix2dos мне нужно было что-то с меньшим количеством ручного вмешательства и более автоматическим через программирование.

Как уже отмечалось, Char (10) работает в строке sql. Я не хотел использовать строку sql, поэтому я использовал '' '' + Char (10) + '' '', но по какой-то причине это не скомпилировалось.

То, что работало очень гладко, было: with (ROWTERMINATOR = '0x0a')

Проблема решена с помощью Hex!

Надеюсь, это кому-нибудь поможет.

14 голосов
/ 26 января 2009

Спасибо всем, кто ответил, но я нашел свое предпочтительное решение.

Когда вы говорите SQL Server ROWTERMINATOR = '\ n', это интерпретирует это как означающий терминатор строки по умолчанию в Windows, который на самом деле является "\ r \ n" (используя нотацию C / C ++). Если ваш терминатор строки действительно просто «\ n», вам придется использовать динамический SQL, показанный ниже.

DECLARE @bulk_cmd varchar(1000)
SET @bulk_cmd = 'BULK INSERT table_name
FROM ''C:\file.csv''
WITH (FIELDTERMINATOR = '','', ROWTERMINATOR = '''+CHAR(10)+''')'
EXEC (@bulk_cmd)

Почему вы не можете сказать, BULK INSERT ... (ROWTERMINATOR = CHAR (10)) вне меня. Не похоже, что вы можете вычислять любые выражения в секции WITH команды.

То, что сделано выше, это создать строку команды и выполнить ее. Аккуратно обходя стороной необходимость создания дополнительного файла или выполнения дополнительных действий.

3 голосов
/ 18 мая 2011

Подтверждаю, что синтаксис

ROWTERMINATOR = '''+CHAR(10)+'''

работает при использовании с командой EXEC.

Если у вас есть несколько символов ROWTERMINATOR (например, канал и перевод строки unix), то синтаксис этого будет:

ROWTERMINATOR = '''+CHAR(124)+''+CHAR(10)+'''
2 голосов
/ 28 мая 2009

Это немного сложнее, чем это! Когда вы указываете SQL Server ROWTERMINATOR = '\ n', это интерпретируется как означающий терминатор строки по умолчанию в Windows, который на самом деле является "\ r \ n" (с использованием нотации C / C ++). Если ваш терминатор строки действительно просто «\ n», вам придется использовать динамический SQL, показанный выше. Я только что провел большую часть часа, выясняя, почему \ n на самом деле не означает \ n при использовании с BULK INSERT!

1 голос
/ 26 января 2009

Один из вариантов - использовать bcp и установить управляющий файл с '\n' в качестве символа разрыва строки.

Хотя вы указали, что предпочитаете этого не делать, другим вариантом будет использование unix2dos для предварительной обработки файла в файл с '\r\n' переносами строк.

Наконец, вы можете использовать опцию FORMATFILE в BULK INSERT. Это будет использовать контрольный файл bcp для указания формата импорта.

0 голосов
/ 26 января 2009

Это сводится к этому. Unix использует LF (ctrl-J), MS-DOS / Windows использует CR / LF (ctrl-M / Ctrl-J).

Когда вы используете '\ n' в Unix, он переводится в символ LF. В MS-DOS / Windows он переводится в CR / LF. Когда ваш импорт выполняется в формате файла Unix, он видит только LF. Следовательно, часто проще сначала запустить файл через unix2dos. Но, как вы сказали в своем первоначальном вопросе, вы не хотите этого делать (я полагаю, есть веская причина, почему вы не можете).

Почему ты не можешь сделать:

(ROWTERMINATOR = CHAR(10))

Возможно, потому что, когда код SQL анализируется, он не заменяет char (10) символом LF (потому что он уже заключен в одинарные кавычки). Или, возможно, его интерпретируют как:

(ROWTERMINATOR =
     )

Что происходит, когда вы выводите содержимое @bulk_cmd?

0 голосов
/ 26 января 2009

Я думаю, что "ROWTERMINATOR = '\ n'" будет работать. Я бы предложил открыть файл в инструменте, который показывает «скрытые символы», чтобы убедиться, что строка заканчивается так, как вы думаете. Я использую блокнот ++ для таких вещей.

0 голосов
/ 26 января 2009

Похоже, есть два основных пути, которые можно использовать: какой-то альтернативный способ чтения CSV в сценарии SQL или преобразования CSV заранее любым из многочисленных способов, которыми вы можете это сделать (bcp, unix2dos, если это одноразовый король, вы, возможно, даже воспользуетесь своим редактором кода, чтобы исправить файл за вас).

Но вам придется сделать дополнительный шаг!

Если этот SQL запускается из программы, вы можете преобразовать окончания строк в этой программе. В этом случае, и вы решаете закодировать преобразование самостоятельно, вот что вам нужно остерегаться: 1. Конец строки может быть \ n 2. или \ r \ n 3. или даже \ r (Mac!) 4. Боже, возможно, некоторые строки имеют \ r \ n, а другие \ n, любая комбинация возможна, если вы не контролируете, откуда взялся CSV

ОК, ОК. Возможность 4 неправдоподобна. Это происходит по электронной почте, но это уже другая история.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...