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);
}