2012-12-28 403 views
4

當插入的字符串長於列允許的字符串時,我的MySQL服務器(通過Windows 2008 Server上的PDO運行)返回錯誤代碼1406(數據字段太長)。事情是我在某處讀到MySQL通常在非嚴格模式下截斷數據的地方。我更改了my.ini中的sql_mode,這樣即使在啓動時它也不會以嚴格模式進入(它當前爲「」),但它仍然給我錯誤並回滾,所以數據丟失(截斷是期望的網站行爲)。插入時自動截斷數據

我輸入到命令行,並在較短的varchar字段中插入一個長字符串,它會截斷數據並保存,但它不是。當我將模式改回嚴格時,它不會在命令行中截斷(只有錯誤)。

此外,我讓網站輸出當前的sql模式,全局和會話(@@ GLOBAL.sql_mode和@@ SESSION.sql_mode),他們都輸出「」,但只是不按需要工作。

有誰知道是什麼造成這個和/或如何改變它?

我懷疑它可能與PDO啓用PDO :: ATTR_ERRMODE = PDO :: ERRMODE_EXCEPTION,但我已閱讀,並找不到有用的東西(我真的不認爲這是肯定的解釋,但我只是把它放在那裏,以便儘可能多地瞭解這個問題)。

非常感謝您

+0

我懷疑這是由於PDO造成的,但有一個簡單的方法來檢查:嘗試從MySQL命令行工具(或其他客戶端)插入一些過長的數據?你如何獲得'sql_mode'變量的值? – eggyal

+0

MySQL(服務器)版本? –

+0

好的,這可能是一個愚蠢的問題,但你爲什麼要它截斷你的數據,而不是告訴你?在我看來,如果它不能存儲你的數據,它應該報告一個錯誤並停止,而不是盲目地接受它,然後把它的一部分扔掉,如果它是一個XML或JSON,你現在不能再解析,那你會怎麼看?錯過了最後? –

回答

3

你真的不應該做的 - 請不要讓壞的數據到數據庫中,並在插入之前清理它在你的腳本。

如果你不知道你的VARCHAR列的實際寬度或不想在腳本中硬編碼,您可以通過使用這樣的查詢查詢INFORMATION_SCHEMA table COLUMNS從數據庫中讀取數據:

SELECT 
    column_name, 
    data_type, 
    character_maximum_length, 
    ordinal_position 
FROM information_schema.columns 
WHERE table_name = 'mytable' 

(您可能希望限制爲data_type = 'varchar')。 有了這些信息,特別是character_maximum_length,你可以使用PHP substr修剪您的輸入字符串到所需的長度。

這種方法的優點是它不會改變任何服務器配置,並且應該適用於任何其他數據庫,而不僅僅是MySQL。

但是,如果你堅持這樣做不安全的方式,你可以嘗試通過執行此暫時禁用嚴格模式:

SET sql_mode = ''; 

之後,MySQL的應該靜靜修剪字符串。閱讀更多here

+0

+1'FROM information_schema.columns' =>有意思的答案! – sdespont

+0

非常感謝。該網站的PHP部分是調用MySQL存儲過程,所以我不能在PHP中修剪,但我想我會做的是一個BEFORE INSERT觸發器來修剪字符串。 'character_maximum_length'仍然有用,因爲從安裝到安裝數據庫模式可能不同,所以它會保持通用。 – aleknaui

0

也許mysql服務器處於「不寬容」模式,又名。傳統(大部分時間)。你讀的是真的,如果MySQL服務器在寬容模式下運行。如果你試圖插入太長的字符串,它可能是非常重要的信息,因此mysql會發出錯誤。你有幾個選擇:

1:使用插入忽略(這將改變所有的錯誤爲警告,將繼續截斷數據)

2:對於當前會話,設置的sql_mode爲「」

這些問題都應該消失。我已經閱讀了你所得到的錯誤,但我仍然認爲服務器是在傳統模式下運行的(所以我推薦sql_mode設置爲空)沒有任何錯誤。

PS2:更改my.cnf後,你重新啓動了mysql服務器嗎?