2017-02-13 1 views
3

Я пытаюсь использовать BULK INSERT для вставки некоторых строк:BULK INSERT вставляет разделитель вместо значения NULL по умолчанию для Empy полей

CREATE TABLE Foo (
    Id UNIQUEIDENTIFIER NOT NULL PRIMARY KEY DEFAULT newsequentialid(), 
    Name NVARCHAR(255) NULL, 
    CreatedOn DATETIME NOT NULL DEFAULT GETDATE(), 
    CreatedBy NVARCHAR(255) NOT NULL DEFAULT SUSER_NAME(), 
    ModifiedOn DATETIME NULL DEFAULT NULL, 
    ModifiedBy NVARCHAR(255) NULL DEFAULT NULL 
); 

Я вставляя из файла CSV, который имеет кодировку UTF8, запятые для разделители, и LF для окончания строки:

,Fizz,,,,, 

Мой BULK INSERT заявление выглядит следующим образом:

BULK INSERT Foo 
FROM 'C:\foo.csv' 
WITH (CODEPAGE = '65001', FIELDTERMINATOR = ',' , ROWTERMINATOR = '0x0a'); 

Но последнее поле вставленной строки (ModifiedBy) имеет значение «» (с запятой delimter:

49625A3B-DCF1-E611-8D73-B00594F7CD91 Fizz 2017-02-13 12:04:48.223 sa NULL , 

Что я делаю неправильно и как мне сделать BULK INSERT вставить последнее поле как NULL (по умолчанию значение) вместо ','?

+2

Я вижу там шесть запятых, последний не требуется. – galactocalypse

ответ

1

Без имена столбцов в первой строке файла данных или значений для каждой позиции в файле, или полной выборки всех изменений строк в файле данных, необходимо либо предположить:

  1. ограничитель строки должен также включать терминатор поля, или
  2. В источнике данных неизвестен дополнительный столбец, который не учитывается в таблице.

Это может быть менее распространено, но полевой терминатор не является редким, чтобы быть включенным в терминатор строки. Фактически, многие из examples on MSDN for bulk insert показывают fieldterminator как ведущую часть rowterminator.

Это решение предполагает, что rowterminator является частью fieldterminator, подобно примерам на MSDN:

bulk insert Foo 
from 'C:\foo.csv' 
with (
    codepage = '65001' 
    , fieldterminator = ',' 
    , rowterminator = '0x2c0a' 
); 

enter image description here

+0

Хотя ваше решение дает желаемый результат, я понимаю, что он ошибается. Основной причиной проблемы является то, что вход имеет семь позиций (для шести запятых), и ваше решение предполагает, что эта дополнительная запятая является частью терминатора строк - для каждой и каждой строки. –

+0

@MarcusViniciusPompeu Я думаю, что это может быть самонадеянно предположить, что мое решение ошибочно. Вы предполагаете, что вход имеет семь позиций, но нет никаких оснований для заключения о том, имеет ли он семь позиций или шесть позиций **, учитывая, что файл не содержит заголовков столбцов или значений для каждой позиции. Я не могу сказать, что более вероятно, но многие [примеры в MSDN для ** 'bulk insert' **] (https://msdn.microsoft.com/en-us/library/ms188365.aspx#Anchor_10) показывают, что 'fieldterminator' как ведущая часть' rowterminator'. – SqlZim

1

Просто посчитайте запятые ...

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

Последняя запятая считается значением для столбца ModifiedBy.

Id,NAME,CreatedOn,CreatedBy,ModifiedOn,ModifiedBy, ?

вход ,Fizz,,,,,,, с семью запятыми, будет оказывать ,, для ModifiedBy.

0

Думаю, у вас есть выбор.

я) изменение объемного метода вставки, вместо того, чтобы использовать OPENROWSET или OPENQUERY.IT позволяют отметить колонку name.Example ссылку,

https://www.mssqltips.com/sqlservertip/1207/different-options-for-importing-data-into-sql-server/

II) Если я) не является приемлемым для вас, то вы можете определить «После вставки» триггера в таблице, где вы можете снова обновить modifiedDate до нуля.

Я думаю решение один прекрасный.

2

Последний столбец таблицы получает все остальные данные во входной строке после назначения других столбцов, по-видимому, без разбора. Если вы поместите 100 запятых в строку ввода, вы получите 95 запятых в последнем столбце импортированной таблицы (я проверил это быстрым тестом). Как отметил Маркус, у вас должно быть 5 разделителей для размещения 6 столбцов.

Если вы не можете удалить дополнительные поля из входного файла, вы можете использовать формат файл для отображения столбца, чтобы исключить последнюю колонку, которая объяснена в: https://msdn.microsoft.com/en-us/library/ms187908.aspx

Если ваш входной файл действительно был предназначен для 6 столбцов, а последний разделитель существует по соглашению, то есть «существует разделитель после каждого столбца» вместо «разделителей между столбцами», тогда решение @ SqlZim должно работать в основном в основном. Но опять же вы должны быть уверены, что после последнего разделителя в строке (например, при ручном редактировании) добавляется белый пробел и т. Д., Иначе импорт не будет выполняться для этой строки, поскольку он не будет соответствовать символам разделителя строк. Поэтому, чтобы быть более безупречным, я бы снова предложил использовать метод сопоставления столбцов, добавив определение фиктивного поля для последнего разделителя и пропуская его во время импорта.

Похоже, сервер Sql намеревается быть гибким или не хочет терять осиротевшие данные, но вызывает больше путаницы, чем полезен.

+0

Достаточно сказано :-) –

Смежные вопросы