2012-12-24 71 views
1

這是我的第一個堆棧溢出文章!社區一直在幫助很大!如何解決存儲過程中沒有「LOAD DATA」支持和/或MySQL中TRANSACTION中缺少EXIT HANDLER的問題?

我有一個90K排CSV我試圖插入表,通過一個臨時表,CSV,如:

CREATE TEMPORARY TABLE temp_product like product; 
LOAD DATA LOCAL INFILE "myfile.csv" 
... 

但我想包插件和一些額外的

CREATE PROCEDURE update_products() 
BEGIN 
    DECLARE EXIT HANDLER FOR SQLEXCEPTION, NOT FOUND, SQLWARNING ROLLBACK; 
    START TRANSACTION; 
    .... 

我喜歡這種方法,因爲它允許在遇到任何錯誤,我自動回滾,而且包裝:通過一個過程,其中包含了交易,並退出處理櫃面出現任何故障,或者拋出一個警告操作很好地處理整個邏輯塊的交易。唉:

Error : LOAD DATA is not allowed in stored procedures 

(我不能肯定這是爲什麼我想這只是目前還不支持?)我不能肯定我的語法正確(或如果這甚至有可能),但我甚至會沒事喜歡的東西:

DECLARE EXIT HANDLER FOR SQLEXCEPTION, NOT FOUND, SQLWARNING ROLLBACK; 
START TRANSACTION; 

但是,這將引發明顯的語法錯誤:

Error : You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DECLARE EXIT HANDLER FOR SQLEXCEPTION, NOT FOUND, SQLWARNING ROLLBACK' at line 1 

看來我可以做這個工作,如果我能以不同的方式加載CSV,但我可能會失去做我的速度批量插入,和/或必須使用基於磁盤的表格,因爲我可能需要與其建立多個連接。據我所知,臨時表只存在於單個連接/事務中,而且我不能100%確定MySQL客戶端navicat如何管理它。

我也不反對用PHP包裝這一切,如果這是最有道理的方式來管理一個腳本,該腳本在與LOAD DATA交易時出現錯誤/警告時會自動回滾。

隨意告訴我,我接近這完全錯了。我覺得可能有更聰明的方式來做我正在做的事情。

回答

2

不幸的是,存儲過程中不支持LOAD DATA INFILE。我記得曾經看到一種解決方法,即有人使用MySQL存儲過程來調用shell腳本來實際執行上傳,但這似乎是一個潛在的問題解決方案,安全方面。您可能可以通過Google解決方案。

最好的辦法可能是使用某種腳本(PHP,shell等)來執行加載到臨時表中,然後調用存儲過程以實際填充到永久表中。我認爲只要你有這件作品的交易支持,你可以回滾真正重要的部分(填充永久表)。

+0

這是一個很好的觀點,謝謝。由於臨時表無論如何都是易失性/非永久性的,因此它可能不需要成爲交易的一部分。我想我擔心臨時表會在事務運行之前消失。只要兩個操作都在同一個連接中進行(即沒有超時),應該沒問題,是的?我想我需要爲我的MySQL客戶端提供RTFM,以瞭解它如何處理連接。 – Andrew

+0

@Andrew只要你使用相同的連接,臨時表應該在那裏。當然,如果臨時表成爲問題,您可以隨時寫入一張真正的表格。 –

+0

我曾經考慮過創建一個基於磁盤的表,以便稍後像您提到的那樣刪除它,但是計算出的開銷會有點多。我想我會做一些基準測試,看看會發生什麼。 – Andrew

相關問題