2013-07-19 42 views
0

我的函數有兩個變量('date',從'date'中減去的月數)。mysql:數據截斷時間值錯誤:函數

這裏是我的功能:

create function a_testbed.PrevMonth (
in_date   date, 
in_mn_count  int) 
RETURNS int 
BEGIN 
/* local variable declaration */ 
declare v_date   int(255); 
declare v_date_format varchar(10); 
declare v_date_sub  varchar(10); 

set v_date_format := DATE_FORMAT(v_date, '%Y-%m'); 
set v_date_sub := DATE_FORMAT(curdate(), '%Y-%m'); 

if (in_date is null) then 
    set v_date := v_date_sub; 
elseif (in_mn_count is null or in_mn_count < 0) then 
    set in_mn_count := 0; 
else 
    set v_date := v_date_sub; 
end if; 
RETURN v_date_format; 
END; 
# 

不斷收到錯誤:

ERROR 1265 (01000) Data Truncated for column 'v_date' at row 1 

有什麼想法?
謝謝!

+0

什麼是確切的錯誤信息? – Barmar

+0

錯誤1265(01000)第1行的列'v_date'的數據被截斷 – user1813619

+0

您是否有理由需要您自己的函數來執行此操作?爲什麼這會返回一個INT而不是DATE? MySQL具有內建函數和表達式以從日期中減去幾個月,例如'dateexpr + INTERVAL -n MONTH'。 – spencer7593

回答

0

我不相信「INT(255)」是一個有效的數據類型。

我知道255只是一個顯示寬度屬性。 INT數據類型定義值的範圍,顯示寬度不影響值的範圍。但是我從來沒有在大於11的INT上看到長度修飾符。(10爲無符號整數)(?)

作爲測試,您可以嘗試指定INT(11),或者只是INT

更大的問題也許是,該數據類型爲INT的變量正在作爲第一個參數傳遞給DATE_FORMAT函數。但DATE_FORMAT的第一個參數需要是DATE,DATETIMETIMESTAMP(iirc)。 INT到DATE可能會有一些隱含的轉換,但我認爲不存在。


我不明白爲什麼你需要一個函數從日期減去的月數。 MySQL內置了函數和簡單的表達式。

例如:

dateexpr + INTERVAL -6個月

返回日期(或DATETIME)6個月值從dateexpr減去。 如果您需要「向下舍入」到本月的第一個月,或者轉換爲只有'yyyy-mm'的字符串,則可以分別執行DATE_FORMAT(dateexpr,'%Y-%m-01')SUBSTRING(dateexpr,1,7)


審查

CREATE FUNCTION a_testbed.PrevMonth (
in_date   date, 
in_mn_count  int) 

這看起來不錯,兩個輸入參數,日期和INT。 (功能參數始終IN參數。)

RETURNS int 

有點奇怪一個名爲PrevMonth函數採用一個DATE參數,但返回一個INT,而不是DATE,但這不是一個錯誤。

BEGIN 
/* local variable declaration */ 
DECLARE v_date   INT(255); 

255的顯示寬度是bizzarre。以前從未在INT上看到過。

DECLARE v_date_format VARCHAR(10); 
DECLARE v_date_sub  VARCHAR(10); 

兩個字符串,看起來不錯。

SET v_date_format := DATE_FORMAT(v_date, '%Y-%m'); 
           ^^^^^^ 

但是v_date是一個INT,而不是DATE或DATETIME。它沒有初始化,所以它是NULL。如果這不會拋出異常,那麼我們期望v_date_format爲NULL。 (我懷疑你想代替v_date在這裏指定in_date

SET v_date_sub := DATE_FORMAT(curdate(), '%Y-%m'); 

這應該讓我們的7個字符,例如「2013年7月」。所以沒有問題。

IF (in_date IS NULL) THEN 
    SET v_date := v_date_sub; 

下面是in_date參數的用法。檢查它是否爲空。如果是,請分配與我們分配給v_date_sub相同的7個字符。得到它了。

ELSEIF (in_mn_count IS NULL OR in_mn_count < 0) THEN 
    SET in_mn_count := 0; 

將值賦給IN參數有效嗎? (這可能是有效的,但它是奇怪的。通常我們不給參數賦值,除非它們是OUT或INOUT參數。我們通常給過程變量賦值(有時候是MySQL用戶變量)。

爲什麼這取決於是否in_date爲空或不是(前面的IF)。好像我們希望在這兩種情況下,以檢查此參數。

ELSE 
    SET v_date := v_date_sub; 

這不是在第一IF指定的相同動作?看來就像這裏的邏輯讀取「如果in_date不爲空,並且ifnull(in_mn_count,-1)」我們做了一件事,否則我們做了其他的事情。我們要麼給IN參數賦值,要麼我們'重新分配將當前的YYYY-MM改爲v_date。

END IF; 

到目前爲止,in_date參數的唯一用途是檢查它是否爲NULL。 in_mn_count參數的唯一用法是嘗試爲其分配一個零值,如果它爲零或小於零。

RETURN v_date_format; 

我們分配什麼v_date_format唯一的一次是在功能的開始,當我們分配從DATE_FORMAT函數的返回,以NULL值傳遞(作爲INT,而不是一個日期。)那麼什麼是所有其他代碼應該在做什麼?

END 

是的,請結束。這個功能有太多的錯誤,它讓我頭痛。所以,請,是的,結束。只要讓它停止。

+0

我認爲你花更多的時間來批評這個功能比他寫的花費更多。 :) – Barmar

+0

@Barmar:我試圖找出它在做什麼。我仍然不知道它爲什麼這麼做。這必須是我所遇到的拋出「數據截斷」錯誤的最巧妙方式。 (順便說一句...我upvoted你的答案。) – spencer7593

0

您指定的varchar到int set v_date := v_date_sub; 更改此:

declare v_date   varchar(10); 
+0

但分配一個VARCHAR到一個INT不應該引發異常。 MySQL逐字符讀取,直到它不能轉換爲整數。如果VARCHAR包含'1234',那麼INT的值爲1234.如果VARCHAR包含'1A2B3C',那麼INT的值爲1. – spencer7593

2

有很多事情不對您的功能:

  1. 你做set v_date_format := DATE_FORMAT(v_date, '%Y-%m');,但是這是你之前assignea值v_date

  2. 後來您指定set v_date := v_date_sub;,但您從未在此之後使用v_date,那麼有什麼意義?

  3. 您指定set in_mn_count := 0;,但從不使用此變量。

  4. 最後你做RETURN v_date_format;v_date_formatVARCHAR,但函數聲明返回INT。該字符串的內容格式爲YYYY-MM,因此它看起來不像整數。

我不知道如果有這些都導致Data truncated錯誤,但幾乎似乎是重要的,當函數很破。

+0

我的大腦處理了這個函數,並拋出一個異常:「'5150什麼塑料?'「 – spencer7593