T-SQL BULK INSERT türü uyuşmazlığı

Oct 15 2020

Büyük bir CSV dosyasından bir tabloya basit bir TOPLU INSERT yapmaya çalışıyorum. Tablo ve dosyanın eşleşen sütunları var. Bu benim kodum:

BULK INSERT myTable
FROM 'G:\Tests\mySource.csv'
WITH (
    FIRSTROW = 2,
    FIELDTERMINATOR = ',',
    ROWTERMINATOR = '\n',
    -- ROWTERMINATOR = '0x0a',
    BATCHSIZE = 1000,
    MAXERRORS = 2
)
GO

Gördüğünüz gibi satır sonlandırıcıları denedim \nve 0x0a(ve bir sürü daha)

Sürekli bir tür uyuşmazlığı hatası alıyorum:

Msg 4864, Level 16, State 1, Line 1
Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 2, column 18 (createdAt).
Msg 4864, Level 16, State 1, Line 1
Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 3, column 18 (createdAt).
Msg 4864, Level 16, State 1, Line 1
Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 4, column 18 (createdAt).
Msg 4865, Level 16, State 1, Line 1
Cannot bulk load because the maximum number of errors (2) was exceeded.
Msg 7399, Level 16, State 1, Line 1
The OLE DB provider "BULK" for linked server "(null)" reported an error. The provider did not give any information about the error.
Msg 7330, Level 16, State 2, Line 1
Cannot fetch a row from OLE DB provider "BULK" for linked server "(null)".

Sütun createdAttürü datetime:

CREATE TABLE [dbo].[myTable]
(
    ...
    [createdAt] [datetime] NULL,
    ...
)

Bunlar createdAt, ilk üç satırdan alınan sütunun değerleridir :

2020-08-22 13:51:57
2020-08-22 14:13:13
2020-08-22 14:16:23

Ayrıca önerildiği gibi farklı bir sayı formatıyla da denedim. Ayrıca sütun türünü şu şekilde değiştirmeyi denedim DATETIME2(n):

2020-08-22T13:51:57
2020-08-22T14:13:13
2020-08-22T14:16:23

Başka ne gözden geçireceğim hakkında hiçbir fikrim yok.

Herhangi bir yardım için minnettar olurum.

Teşekkürler!

Yanıtlar

2 marc_s Oct 15 2020 at 16:47

SQL Server tarafından desteklenen tarih ve saatlere dönüştürülecek pek çok değişmez dize biçimi vardır - CAST ve CONVERT'teki Çevrimiçi MSDN Kitaplarına bakın . Bu formatların çoğu, sahip olduğunuz ayarlara bağlıdır - bu nedenle, bu ayarlar bazen işe yarayabilir - ve bazen çalışmayabilir. Ve DATETIMEözellikle veri türü, dizge değişmezlerinin hangi formatlarının işe yaradığı ve diğerlerinin (çoğu) çalışmadığı konusunda herkesin bildiği gibi seçicidir ... DATETIME2(n)çok daha bağışlayıcı ve uğraşması daha az seçici!

Bunu çözmenin yolu, SQL Server tarafından desteklenen (biraz uyarlanmış) ISO-8601 tarih biçimini kullanmaktır - bu biçim her zaman çalışır - SQL Server diliniz ve tarih biçimi ayarlarınızdan bağımsız olarak.

ISO-8601 biçiminde SQL Server tarafından desteklenen iki şekilde sağlanır:

  • YYYYMMDDsadece tarihler için (zaman bölümü yok); buraya dikkat edin: tire yok! bu çok önemli! YYYY-MM-DDolduğu DEĞİL SQL Server dateformat ayarlarından bağımsız ve olacak DEĞİL her durumda çalışmayabilir!

veya:

  • YYYY-MM-DDTHH:MM:SStarihler ve saatler için - burada not: Bu biçim vardır tire (ama olabilir atlanabilir) ve sabit Taramalarınızdan tarih ve saat kısmı arasında ayırıcı olarak DATETIME.

Bu, SQL Server 2000 ve sonrası için geçerlidir.

SQL Server 2008 veya daha DATEyenisini ve veri türünü (yalnızca DATE- değil DATETIME !) Kullanıyorsanız , o zaman YYYY-MM-DDformatı da kullanabilirsiniz ve bu da SQL Server'ınızdaki herhangi bir ayar ile çalışacaktır.

Bana tüm bu konunun neden bu kadar zor ve biraz kafa karıştırıcı olduğunu sorma - bu tam olarak böyle. Ancak YYYYMMDDbiçimle, SQL Server'ın herhangi bir sürümü ve SQL Server'ınızdaki herhangi bir dil ve tarih biçimi ayarı için iyi olmalısınız.

SQL Server 2008 ve daha yeni sürümler için öneri, DATEyalnızca tarih kısmına ve DATETIME2(n)hem tarih hem de saate ihtiyacınız olduğunda kullanmanızdır. DATETIMEMümkünse veri türünü aşamalı olarak kaldırmaya başlamalısınız

Senin durumunda, iki şeyden birini denerim:

  • Eğer yapabiliyorsanız - sütununuzun veri türü DATETIME2(n)yerine kullanın DATETIME- bu tek başına tüm sorunlarınızı çözebilir

  • kullanamıyorsanız DATETIME2(n)- CSV içe aktarma dosyasında tarih ve saatinizi belirtmek 2020-08-22T13:51:57yerine kullanmayı deneyin 2020-08-22 13:51:57.