Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

freebcp :les données Unicode ont une taille d'octet impaire pour la colonne. Doit être de taille paire en octets

Mise à jour :ce problème a apparemment été résolu dans FreeTDS v1.00.16, publié le 04/11/2016.

Je peux reproduire votre problème en utilisant FreeTDS v1.00.15. Cela ressemble définitivement à un bogue dans freebcp qui le fait échouer lorsque le dernier caractère d'un champ de texte a un point de code Unicode de la forme U+20xx . (Merci à @srutzky d'avoir corrigé ma conclusion quant à la cause.) Comme vous l'avez noté, cela fonctionne ...

291054  Ţawī Rifā

... et cela échoue ...

291054  Ţawī Rifā‘

... mais j'ai trouvé que ça marche aussi :

291054  Ţawī Rifā‘x

Ainsi, une solution de contournement laide serait d'exécuter un script sur votre fichier d'entrée qui ajouterait un caractère Unicode non-espace de poids faible à chaque champ de texte (par exemple, x qui est U+0078 , comme dans le dernier exemple ci-dessus), utilisez freebcp pour télécharger les données, puis exécutez une UPDATE sur les lignes importées pour supprimer le caractère supplémentaire.

Personnellement, je serais enclin à passer de FreeTDS au pilote ODBC SQL Server de Microsoft pour Linux, qui inclut le bcp et sqlcmd utilitaires lorsqu'ils sont installés en suivant les instructions décrites ici :

https://gallery.technet.microsoft.com /scriptcenter/SQLCMD-et-BCP-pour-Ubuntu-c88a28cc

Je viens de le tester sous Xubuntu 16.04, et même si j'ai dû modifier un peu la procédure pour utiliser libssl.so.1.0.0 au lieu de libssl.so.0.9.8 (et pareil pour libcrypto ), une fois que je l'ai installé, le bcp utilitaire de Microsoft a réussi où freebcp échoué.

Si le pilote ODBC SQL Server pour Linux ne fonctionne pas sur un Mac, une autre alternative serait d'utiliser le pilote Microsoft JDBC 6.0 pour SQL Server et un peu de code Java, comme ceci :

connectionUrl = "jdbc:sqlserver://servername:49242"
        + ";databaseName=myDb"
        + ";integratedSecurity=false";
String myUserid = "sa", myPassword = "whatever";

String dataFileSpec = "C:/Users/Gord/Desktop/bad.txt";
try (
        Connection conn = DriverManager.getConnection(connectionUrl, myUserid, myPassword);
        SQLServerBulkCSVFileRecord fileRecord = new SQLServerBulkCSVFileRecord(dataFileSpec, "UTF-8", "\t", false);
        SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(conn)) {
    fileRecord.addColumnMetadata(1, "col1", java.sql.Types.NVARCHAR, 50, 0);
    fileRecord.addColumnMetadata(2, "col2", java.sql.Types.NVARCHAR, 50, 0);
    bulkCopy.setDestinationTableName("dbo.freebcptest");
    bulkCopy.writeToServer(fileRecord);
} catch (Exception e) {
    e.printStackTrace(System.err);
}