¿Cómo escribir caracteres UTF-8 utilizando inserción masiva en SQL Server?

Estoy haciendo un BULK INSERT en sqlserver y no está insertando correctamente los caracteres UTF-8 en la base de datos. El archivo de datos contiene estos caracteres, pero las filas de la base de datos contienen caracteres basura después de la ejecución de la inserción masiva.

Mi primer sospechoso fue la última línea del archivo de formato:

10.0 3 1 SQLCHAR 0 0 "{|}" 1 INSTANCEID "" 2 SQLCHAR 0 0 "{|}" 2 PROPERTYID "" 3 SQLCHAR 0 0 "[|]" 3 CONTENTTEXT "SQL_Latin1_General_CP1_CI_AS" 

Pero, después de leer esta página oficial, me parece que esto es realmente un error al leer el archivo de datos mediante la operación de inserción en SQL Server versión 2008. Estamos usando la versión 2008 R2.

¿Cuál es la solución a este problema o al menos una solución?

No puedes. Primero debe usar un campo de datos de tipo N, convierta su archivo a UTF-16 y luego impórtelo. La base de datos no es compatible con UTF-8.

Vine aquí antes de buscar una solución para insertar caracteres especiales a granel. No me gustó la solución con UTF-16 (que duplicaría el tamaño del archivo csv). Descubrí que definitivamente CAN y es muy fácil, no necesita un archivo de formato. Así que estoy agregando este comentario para otras personas que están buscando lo mismo, ya que no parece estar bien documentado en ninguna parte, y creo que este es un problema muy común para las personas que no hablan inglés. La solución es: simplemente agregue CODEPAGE = ‘65001’ dentro de la instrucción with de la inserción masiva. (65001 = número de página de códigos para UTF-8). Puede que no funcione para todos los caracteres Unicode como sugiere Michael O, pero al menos funciona perfecto para latin-extended, griego y cirílico, probablemente también para muchos otros.

Nota: La documentación de MSDN dice que utf-8 no es compatible, no lo creo, para mí esto funciona perfectamente en SQL Server 2008, sin embargo, no intenté con otras versiones.

p.ej:

 BULK INSERT #myTempTable FROM 'D:\somefolder\myCSV.txt'+ WITH ( CODEPAGE = '65001', FIELDTERMINATOR = '|', ROWTERMINATOR ='\n' ); 

Si todos sus caracteres especiales están en 160-255 (iso-8859-1 o windows-1252), también puede usar:

 BULK INSERT #myTempTable FROM 'D:\somefolder\myCSV.txt'+ WITH ( CODEPAGE = 'ACP', FIELDTERMINATOR = '|', ROWTERMINATOR ='\n' ); 
  1. En excel guardar archivo como CSV (delimitado por comas)
  2. Abra el archivo CSV guardado en el bloc de notas ++
  3. Codificación -> Convertir tO UCS-2 Big Endian
  4. Salvar

BULK INSERT #tmpData

  FROM 'C:\Book2.csv' WITH ( FIRSTROW = 2, FIELDTERMINATOR = ';', --CSV field delimiter ROWTERMINATOR = '\n', --Use to shift the control to next row TABLOCK ) 

Hecho.

Microsoft acaba de agregar soporte UTF-8 a SQL Server 2014 SP2:

https://support.microsoft.com/en-us/kb/3136780

Puede volver a codificar el archivo de datos con UTF-16. Eso es lo que hice de todos modos.

¿No deberías estar usando SQLNCHAR lugar de SQLCHAR para los datos Unicode?

Utilice estas opciones – DATAFILETYPE='char' y CODEPAGE = '1252'

Tenga en cuenta que a partir de Microsoft SQL Server 2016, UTF-8 es compatible con bcp , BULK_INSERT (como era parte de la pregunta original) y OPENROWSET .

Pude hacer esto usando SSIS y un destino ADO NET en lugar de OLEDB.

Mis datos exportados están en formato TSV desde DB que tiene encoding Latin-1.

Esto es fácil de verificar: SELECT DATABASEPROPERTYEX('DB', 'Collation') SQLCollation;

El archivo de extracción está en formato UTF-8.

BULK INSERT no funciona con UTF-8, así que convierto UTF-8 a ISO-8859-1 (también conocido como Latin-1) con un simple script Clojure:

(spit ".\\dump\\file1.txt" (slurp ".\\dump\\file1_utf8.txt" :encoding "UTF-8") :encoding "ISO-8859-1")

Para ejecutar: corrija las rutas y java.exe -cp clojure-1.6.0.jar clojure.main utf8_to_Latin1.clj

He probado la inserción masiva con formato UTF -8 . Funciona bien en Sql Server 2012.

 string bulkInsertQuery = @"DECLARE @BulkInsertQuery NVARCHAR(max) = 'bulk insert [dbo].[temp_Lz_Post_Obj_Lvl_0] FROM ''C:\\Users\\suryan\\Desktop\\SIFT JOB\\New folder\\POSTdata_OBJ5.dat'' WITH ( FIELDTERMINATOR = '''+ CHAR(28) + ''', ROWTERMINATOR = ''' +CHAR(10) + ''')' EXEC SP_EXECUTESQL @BulkInsertQuery"; 

Estaba usando el archivo *.DAT con FS como separador de columna.

Pensé que agregaría mis pensamientos a esto. Intentamos cargar datos en SqlServer usando bcp y tuvimos muchos problemas.

bcp no admite, en la mayoría de las versiones, ningún tipo de archivos UTF-8. Descubrimos que UTF-16 funcionaría, pero es más complejo de lo que se muestra en estas publicaciones.

Usando Java escribimos el archivo usando este código:

 PrintStream fileStream = new PrintStream(NEW_TABLE_DATA_FOLDER + fileName, "x-UTF-16LE-BOM"); 

Esto nos dio los datos correctos para insertar.

utf-16 little-endian

Intentamos usar solo UTF16 y seguimos recibiendo errores EOF. Esto es porque nos faltaba la parte BOM del archivo. De la Wikipedia:

UTF-16, una BOM (U + FEFF) se puede colocar como el primer carácter de un archivo o secuencia de caracteres para indicar el endianness (orden de bytes) de todas las unidades de código de 16 bits del archivo o secuencia.

Si estos bytes no están presentes, el archivo no funcionará. Así que tenemos el archivo, pero hay un secreto más que debe abordarse. Al construir su línea de comando, debe incluir -w para decirle a bcp qué tipo de datos es. Cuando use solo datos en inglés, puede usar -c (carácter). Entonces se verá algo como esto:

bcp dbo.blah en C: \ Users \ blah \ Desktop \ events \ blah.txt -S tcp: databaseurl, someport -d thedatabase -U username -P password -w

¡Cuando todo esto termine, obtendrás datos atractivos!

¡Buen pequeño endian!