2017-02-23 81 views
7

我正在使用Ubuntu,我正在使用DBeaver進行數據庫訪問。我試圖將拉丁字符插入到數據庫(MSSQL)中,並引發錯誤。但是如果我插入與DBeaver相同的特殊字符,它不會引發任何錯誤並且它正在工作。我已經看到this的問題。但我沒有任何想法。如何在數據庫中插入特殊字符?

它拋出以下錯誤:

DBD::ODBC::st execute failed: [unixODBC][FreeTDS][SQL Server]Error converting characters into server's character set. Some character(s) could not be converted (SQL-HY000) at expert.fi_review.pl line 243. 

和數據db是J�rjest�myyr�。但實際數據是Järjestömyyrä

示例代碼:

my ($dsn,$dbh); 
&DB_Connect; 

$insert_query = "INSERT INTO table_name (name) values(N'$name')"; 
my $sth = $dbh->prepare($insert_query); 
$sth->execute() or $DB_Error=$DBI::errstr; 

sub DB_Connect 
{ 
    $dsn = "dbi:ODBC:driver={SQL Server};Server=$Server_name,$port;database=$Database_name;driver=FreeTDS;tds_version=8.0;"; 
    reconnect: $dbh = DBI->connect($dsn, $db_user_id, $db_pwd ,{AutoCommit => 1}) or goto reconnect; 
    $dbh-> {'LongTruncOk'} = 1; 
    $dbh-> {'LongReadLen'} = 90000; 
} 
+0

是你的sql表字段nvarchar?如果沒有,請嘗試。 –

+0

你可以顯示你的代碼嗎? – Steven

+0

@SeanB是的。我的sql表只有'nvarchar'類型。 – mkHun

回答

-1

你的錯誤是錯誤分類與SQL Server,因爲錯誤是使用Perl的這哪裏是故障發生時您的客戶端。

除此之外,當使用第三方庫和管理工具時,如果不需要功能性或美元明智的功能,並且支持更少。

正如此處的評論者告訴您的,Umlaut文本是Unicode字符,因此列需要是nvarchar或nText。 https://msdn.microsoft.com/en-us/library/ms186939.aspx

如果您選擇使用SSMS和SSDT,我相信SQL Server社區將爲您提供更好的支持。沒有必要使用Perl來完成這個簡單的數據傳輸。

SQLSTATE [HY000]:常規錯誤:有口音的外地1366不正確的字符串值 -

非常相似問題出現here as well

0

在將utf-8插入到nvarchar列之前,將utf-8轉換爲utf-16。

在閱讀時回到utf-8。

或者使用varbinary列並在其中存儲普通的utf-8字節。將utf-8編碼數據存儲在nvarchar列中是錯誤的。

0

你可以嘗試改變你的代碼嗎?

$insert_query = "INSERT INTO table_name (name) values(?)"; 
my $sth = $dbh->prepare($insert_query); 
$sth->bind_param(1, $name, DBI::SQL_WVARCHAR); 
$sth->execute() or $DB_Error=$DBI::errstr; 
0

轉換領域utf8_unicode_ci

例子:ALTER TABLE t CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;

或者如果它是一個查詢:

SELECT * FROM `INFORMATION_SCHEMA.COLUMNS` 
WHERE TABLE_SCHEMA = 'dbname' AND CHARACTER_SET_NAME = 'latin1' 
0

從你的問題,當問題涉及目前尚不清楚。

如果是從Perl中,您可以使用url escape function

use URI::Escape; 
my $string = "Järjestömyyrä"; 
my $encode = uri_escape($string); 
my $decode = uri_unescape($encode); 

一個JavaScript替代預覽這裏

var a="Järjestömyyrä"; 
 
var b=encodeURIComponent(a); 
 
console.log("Encode : "+b); 
 
console.log("Decode : "+decodeURIComponent(b));

如果問題來簡單地進行編碼當您嘗試直接插入到數據庫時,

然後,你必須改變表結構,並設置CHARSET to latin1

ALTER TABLE table_name ALTER COLUMN name varchar(20) COLLATE Latin1_General_CI_AS NOT NULL; 

這些鏈接將幫助您完成此:

1:http://kunststube.net/frontback/
2:https://msdn.microsoft.com/en-us/library/ms190920.aspx

1

嗯。我向FreeTDS添加了iconv支持,並在某種意義上負責了該錯誤消息。我有三個問題和一個建議。

  1. 什麼是目標列的編碼,table_name.name?該編碼是否支持你試圖插入的字符?我打賭不是。

  2. freetds.conf中的客戶端字符集是否與區域設置(1)中反映的字符集匹配?

  3. 你確定你沒有使用舊的TDS協議版本4.1嗎?

FreeTDS將SQL文本轉換爲UTF-16。當您將數據內插到SQL insert語句中時,FreeTDS將轉換整個語句,數據和全部語句。如果客戶端編碼描述不正確,則無法轉換數據。如果服務器編碼無法表示字符,則無法轉換數據。如果協議是古老的,就不會支持Unicode。

從您的錯誤消息很難說,但它在我看來像客戶端成功和服務器端失敗。也就是說,FreeTDS將數據正確地轉換爲UTF-16,但服務器無法將數據插入到name列中,因爲它是varchar而不是nvarchar,並且數據庫(或列,如果指定)的「代碼頁」爲不能代表那些角色。

我的建議是使用TDS_DUMP並加入FreeTDS郵件列表。 TDS_DUMP日誌將回答我提出的所有問題。你會在郵件列表中獲得更好的支持,因爲它是專門的。

那麼你可能會問,爲什麼DBeaver似乎工作。我不知道;我從來沒有聽說過它。我可以告訴你有辦法插入數據(例如,在ODBC中使用參數化查詢),服務器只是簡單地插入數據。奇怪的是,它並沒有驗證它們對聲明的編碼有效。

我幫了很多人解決這個問題。數據庫是爲CP-1252設置的,但數據編碼不正確。應用程序可以插入錯誤編碼的數據,稍後檢索並正確渲染它們,然後滑入雷達。但讓DBA嘗試查詢數據或使用正常的管理工具檢查它們,並且他們看起來很有趣。服務器假定其數據庫中的數據按照數據庫定義進行編碼。如果不是這種情況發生,就會發生鬧劇!

如果這是你的情況,你可以很容易地測試它。使用DBeaver插入數據。使用SQL Server管理應用程序或舊的isql,在Windows上檢索它。賠率是你不會被逗樂。