0

私の関数には2つの変数があります(「日付」、「日付」から減算する月数)。

ここに私の機能があります:

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

何かご意見は?
ありがとう!

4

3 に答える 3

2

関数には多くの問題があります。

  1. しますがset v_date_format := DATE_FORMAT(v_date, '%Y-%m');、これは に値を割り当てる前ですv_date

  2. 後で を割り当てますがset v_date := v_date_sub;、その後は決して使用v_dateしないので、ポイントは何ですか?

  3. を割り当てますがset in_mn_count := 0;、この変数も決して使用しません。

  4. 最後に、あなたはそうしますRETURN v_date_format;v_date_formatは ですVARCHARが、関数は を返すように宣言されていINTます。また、この文字列の内容は の形式YYYY-MMであるため、整数のようには見えません。

これらのいずれかがエラーの原因であるかどうかはわかりませんがData truncated、関数が非常に壊れている場合、それはほとんど重要ではないようです.

于 2013-07-19T04:12:49.410 に答える
0

INT(255)" " は有効なデータ型ではないと思います。

255 は単なる表示幅属性であることはわかっています。INT データ型は値の範囲を定義し、表示幅は値の範囲に影響しません。しかし、11 より大きい INT の length 修飾子を見たことがありません (unsigned int の場合は 10) (?)

テストとして、INT(11)、または だけを指定してみてくださいINT

さらに問題なのは、データ型を持つこの変数が関数INTの最初の引数として渡されていることDATE_FORMATです。ただし、 の最初の引数は、または(iirc)でDATE_FORMATある必要があります。INT から DATE への暗黙の変換があるかもしれませんが、ないと思います。DATEDATETIMETIMESTAMP


DATE から月数を減算する関数が必要な理由がわかりません。MySQL には組み込み関数と、それを行う単純な式があります。

例えば:

dateexpr + INTERVAL -6 MONTH

から 6 か月を引いた DATE (または DATETIME) 値を返しますdateexpr。月の最初に「切り捨てる」必要がある場合、または「yyyy-mm」だけの文字列に変換する必要がある場合は、それぞれ aDATE_FORMAT(dateexpr,'%Y-%m-01')または aを実行できますSUBSTRING(dateexpr,1,7)


レビュー

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

2 つの入力パラメーター、DATE と INT で問題ないようです。(関数パラメータは常に IN パラメータです。)

RETURNS int

PrevMonthという名前の関数が DATE 引数を取りますが、DATE ではなく INT を返すのは少し奇妙ですが、これはエラーではありません。

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

255 の表示幅は奇妙です。前にINTでそれを見たことがない。

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

2弦、いい感じです。

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

ただしv_date、DATE または DATETIME ではなく、INT です。また、初期化されていないため、NULL です。これが例外をスローしない場合は、v_date_formatNULL であると予想されます。in_date(の代わりにここで指定したかったのではないかと思いますv_date。)

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

これにより、「2013-07」のように 7 文字になります。問題ありません。

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

in_dateパラメータの使用法は次のとおりです。null かどうかを確認します。そうであれば、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 が null かどうかに依存するのはなぜですか (前の IF)。どちらの場合でも、このパラメータをチェックしたいようです。

ELSE
  SET v_date := v_date_sub;

これは、最初の で指定された同じアクションではありませんIFか? ここのロジックは、「in_date が null ではなく、ifnull(in_mn_count,-1)<0 の場合」と読み、1 つのことを行い、それ以外の場合は別のことを行うようです。IN パラメータに値を割り当てようとしているか、現在の YYYY-MM を v_date に割り当てています。

END IF;

これまでのところ、in_date パラメータの唯一の用途は、それが NULL かどうかを確認することでした。また、in_mn_count パラメータの唯一の使用法は、null またはゼロ未満の場合にゼロを割り当てようとすることです。

RETURN v_date_format;

何かを代入しv_date_formatたのは関数の最初だけで、DATE_FORMAT 関数からの戻り値を代入し、NULL 値を (DATE ではなく INT として) 渡しました。してる?

END

はい、終了してください。この関数には多くの間違いがあり、頭が痛くなります。では、はい、END でお願いします。やめさせるだけ。

于 2013-07-19T03:51:54.190 に答える
0

varchar を int に割り当てますset v_date := v_date_sub; これを変更します。

declare v_date         varchar(10);
于 2013-07-19T03:58:17.437 に答える