ストアドファンクションのエラーについて

このQ&Aのポイント
  • PostgreSQLで作成したストアドファンクションがエラーを出力しています。
  • エラーの内容は「value too long for type character varying(5)」です。
  • 原因がわからず困っています。ご教授いただけると助かります。
回答を見る
  • ベストアンサー

ストアドファンクションのエラーについて

PostgreSQLでストアドファンクションを作成しました。 ファンクションの内容は下記の通りです。 CREATE FUNCTION getRenban (VARCHAR) RETURNS VARCHAR(7) AS ' DECLARE key ALIAS FOR $1; code VARCHAR(7); code2 VARCHAR(2); code5 VARCHAR(5); renban INTEGER; new_code VARCHAR(7); BEGIN SELECT MAX(code) INTO code FROM M_ITEM WHERE flg = TRIM($1); code2 := TRIM($1); IF code IS NULL THEN renban := 1; ELSE SELECT SUBSTR(code, 2) INTO code5; SELECT TO_NUMBER(code5, ''99999'') INTO renban; renban := renban + 1; END IF; code5 := ''''; SELECT TO_CHAR(renban, ''00000'') INTO code5; SELECT code2 || code5 INTO new_code; RETURN new_code; END; ' language 'plpgsql' ; コンソール上で下記のコマンドを実行したらエラーが出力されました。 SELECT getrenban('01'); 出力されたエラーの内容は下記の通りです。 ERROR: value too long for type character varying(5) CONTEXT: PL/pgSQL function "getrenban" line 19 at SQL statement お恥ずかしいですがいくらコードを見てもどこが原因なのかわかりません。 申し訳ありませんがご教授お願いできませんでしょうか。 昨日から悩んでいます。 どうか助けて下さい、宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • utakataXEX
  • ベストアンサー率69% (711/1018)
回答No.1

>ERROR: value too long for type character varying(5) >CONTEXT: PL/pgSQL function"getrenban" line 19 at SQL statement line 19と言う事は code5 := ''''; SELECT TO_CHAR(renban, ''00000'') INTO code5; ↑ この辺ですよね。 で、「長過ぎてvarchar(5)に入れられない」と怒られています。 PL/pgSQLは実務で使った事がないのですが、オラクルのPL/SQLの観点で回答します。 5桁の数字が入ったintegerの変数をTO_CHARすると結果は6桁になります。 +-が一桁付加されるからです。 (正の場合は半角スペース) なので「長過ぎてvarchar(5)に入れられない」と怒られたわけです。 代入時にスペースをトリムすれば解決します。 それと、クリア時のダブルクォートが気になりましたが、コンパイルが通っているので、これは問題無いのでしょうね。

j-unico
質問者

お礼

回答ありがとうございます。 知りませんでした。 結果が6桁になるなんて・・・ 大変、勉強になりました。 本当に助かりました、ありがとうございました。

その他の回答 (1)

  • utakataXEX
  • ベストアンサー率69% (711/1018)
回答No.2

1点気になりましたが、複数セッ ションからの同時アクセスに ついての要件はどうなっています でしょうか? これだと同時アクセスの際に、 運が悪ければ同じ連番になって しまいます。 通常はこの手の場合、シーケンス オブジェクトを使用します。 (重複する事なく、カウントアップ できます) 要件的に許されるのであれば、今 の作りでもよいですが、そうで なければ、シーケンスの使用を 検討してください。

関連するQ&A

  • ストアドファンクションがうまく作成できない

    SQL Server 2005 にて、 以下のようなストアドファンクションを作成しようとしても、 「メッセージ 156、レベル 15、状態 1、プロシージャ TestKansu、行 30 キーワード 'end' 付近に不適切な構文があります。」 といったエラーメッセージが表示されてしまい、 うまく作成できません。。 文法など、いろいろ調べてみたところ、特に問題なさそうな 感じではあるのですが。。 どこに問題があるのか、どなたかご教授願えないでしょうか? なにとぞ、よろしくお願いいたします。 -------------------------------- use tempdb go -- 呼び出し形式 create function TestKansu ( @Date as datetime, @Type as varchar(1) ) returns @ReturnTable table ( StartDate varchar(8), EndDate varchar(8) ) as begin if @Type is null begin raiserror('正しいtypeを指定してください',-1,-1) end if @Date is null begin SET @Date = getdate() end if @Type = '0' begin insert into @ReturnTable select convert(varchar(8), dateadd(dd ,-2 ,@Date), 112) as StartDate, convert(varchar(8), dateadd(dd ,-2 ,@Date), 112) as EndDate, end if @Type = '1' begin insert into @ReturnTable select convert(varchar(8), @Date, 112) as StartDate, convert(varchar(8), @Date, 112) as EndDate end return end --------------------------------

  • ファンクション内での円マークについて

    値をカンマ形式で変換するファンクションを作成しています。 ファンクションの内容は下記の通りです。 CREATE FUNCTION Test (DECIMAL) RETURNS VARCHAR(15) AS ' DECLARE arg ALIAS FOR $1; str VARCHAR(16); BEGIN str := ''''; SELECT TRIM(TO_CHAR(arg, ''\\9,999,999,999'')) INTO str; RETURN str; END; ' language 'plpgsql' ; 上記のコマンドを実行したらワーニングが出力されました。 下記が出力したワーニングの内容です。 WARNING: nonstandard use of \\ in a string literal 行 2: ' ^ HINT: Use the escape string syntax for backslashes, e.g., E'\\'. WARNING: nonstandard use of escape in a string literal 行 1: SELECT TRIM(TO_CHAR( $1 , '\9,999,999,999')) ^ HINT: Use the escape string syntax for escapes, e.g., E'\r\n'. QUERY: SELECT TRIM(TO_CHAR( $1 , '\9,999,999,999')) CONTEXT: SQL statement in PL/PgSQL function "test" near line 6 CREATE FUNCTION ※一応、ファンクションは作成できたんですで・・・ ファンクションを実行したらワーニングと結果が出力されました。 SELECT test(10000); 下記が出力したワーニングの内容です。 WARNING: nonstandard use of escape in a string literal 行 1: SELECT TRIM(TO_CHAR( $1 , '\9,999,999,999')) ^ HINT: Use the escape string syntax for escapes, e.g., E'\r\n'. QUERY: SELECT TRIM(TO_CHAR( $1 , '\9,999,999,999')) CONTEXT: PL/pgSQL function "test" line 6 at SQL statement test -------- 10,000 (1 行) 下記のように円マークの箇所にEをつけたりしましたがワーニングが解消する事はできませんでした。多分、私の記述がいけないような気がします。 すみませんがどのように記述すればいいのでしょうか。 ご教授いただけませんでしょうか。 宜しくお願いします。

  • テーブル名が可変の動的SQLをファンクションにしたい

    Oracle9iのWindowsXP環境です。 以下のようなPL/SQLを作成しましたが、同じようなselect文の繰り返しなので整理したいのと、レスポンスが悪いのでファンクションにしたいのですが、テーブル名が可変のため上手くいきません。「Table&1」は置換変数で、batファイルからパラメータが渡り、「Table200812」のように変更されます。 【***.bat】 set /p phara sqlplus -s ***/***@*** ***.sql %phara% 【***.sql】 省略 begin select aaa into a1 from Table&1 where code = 'AAAAA'; ・・ select aaa into a2 from Table&1 where code = 'BBBBB'; ・・ select aaa into a3 from Table&1 where code = 'CCCCC'; ・・ 省略 end; / 以下、試しに作成しようとしたファンクションですが、やはり予想どおりですが「表がありません」とコンパイルエラーになります。 create function Func_test(code IN varchar2, Table1 IN varchar2) return number is ret number; begin select aaa into ret from Table1 where code = 'code'; return ret; end; / ※コール側は、「a1 = Func_Test('AAAAA', Table&1);」 そもそもこれが実現できたとしてレスポンスが上がるものなのでしょうか?どちらにせよコードを整理する意味でもファンクションにはしたいのですが。。 宜しくお願い致します。

  • ストアドファンクションの戻り値をテーブルに・・

    SQL/PLUSにて作成したファンクションの戻り値で返ってきた文字列をテーブル名として使用するにはどうすればよいのでしょうか?? まず以下のようにSQL/PLUSにてFUNCTIONを作成しました。 create or replace function FuncXXXXX (inA varchar2) return varchar2 is OutA varchar2; begin select MAX(table_name) into outA from all_tables where table_name like inA || '%'; return outA end; / それを以下省略ですが、テーブルでコールしようとするとエラー(ORA-00905:キーワードがありません)が発生します。このような使い方はできないのでしょうか? select   ・   ・ from AAAA inner join FuncXXXXX(inA) ※execute FuncXXXXX(inA)でも同様 on   ・   ・ 申し訳ありませんが宜しくお願いします。

  • ストアド内で実行したSQLの出力結果について

    現在、引数の値を元に下記のようなSQL文を生成しています。 SELECT code, name FROM T_CGY WHERE code = '1111' UNION SELECT code, name FROM T_CGY WHERE code = '1110' UNION SELECT code, name FROM T_CGY WHERE code = '1100' UNION SELECT code, name FROM T_CGY WHERE code = '1000' ORDER BY code; ※出力されたSQL文に誤りがないかを確認する為にコピーしてターミナル上で実行したら該当するレコードを取得する事ができました。 それをストアドプロシージャ内で生成したSQL文を「QUERY EXECUTE」を実行して該当するレコードが取得できるように改造してみました。 下記が出力された結果です。 getCgyData -------------------- (1000,洋服) (1100,子供服) (1110,ズボン) (1111,長ズボン) 出力されたデータは私が望んだ内容なんですが・・・ 私的には下記のように出力したいと考えています。 col1    | col2 ------------------------- 1000  | 洋服 1100  | 子供服 1110  | ズボン 1111  | 長ズボン 何とか上記のように出力できるようにするにはどうしたらいいでしょうしょうか。 そもそも上記のように出力する事は可能なのでしょうか。 CREATE FUNCTION getCgyData (VARCHAR) RETURNS TABLE(col1 VARCHAR, col2 VARCHAR) AS ' DECLARE key ALIAS FOR $1; sql TEXT; BEGIN                 ・                 ・ ※ここでSQL文を生成して、変数(sql)に格納しています。                 ・                 ・ RETURN QUERY EXECUTE sql; END; ' language 'plpgsql' ; データベースのバージョンはpostgreSQL8.4.9です。 再度、申し訳ありませんがアドバイス、宜しくお願いします。 では、失礼します。

  • Mysql ストアドファンクション 意図しない結果

    以下の通りストアドファンクションを作成しました。 関数名:fgetLineNew インパラメータ:shop Varchar 8 ※1つだけ。。。 戻り値: Int 11 <ソース> BEGIN DECLARE pline INTEGER(11) DEFAULT NULL; SELECT COUNT(1) INTO pline FROM `hoge` WHERE `SHOP` = shop; IF pline IS NULL THEN SET pline = 10000; END IF; RETURN pline; END 上記のように、作成したストアドファンクションですが、 どんな引数を入れても、戻り値が全ての行(817行)になってしまいます。 以下を参照。 Where区がまったく働いていないのですが、何が原因なのでしょうか。 教えてください。 <ストアドファンクション実行> mysql> select fgetLineNew(1); +----------------+ | fgetLineNew(1) | +----------------+ | 817 | +----------------+ 1 row in set (0.01 sec) mysql> select fgetLineNew(525); +------------------+ | fgetLineNew(525) | +------------------+ | 817 | +------------------+ 1 row in set (0.01 sec) mysql> select fgetLineNew(101); +------------------+ | fgetLineNew(101) | +------------------+ | 817 | +------------------+ 1 row in set (0.00 sec) mysql> select fgetLineNew(525); +------------------+ | fgetLineNew(525) | +------------------+ | 817 | +------------------+ 1 row in set (0.00 sec) mysql> select fgetLineNew('525'); +--------------------+ | fgetLineNew('525') | +--------------------+ | 817 | +--------------------+ 1 row in set (0.01 sec)

    • ベストアンサー
    • MySQL
  • ストアドファンクション⇒プロシージャ呼出し失敗する

    参考の通りに、ストアドプロシージャ作成SQL文を発行し、 コマンドライン上からは、以下の通りの結果1となり、 レコードがinsertされます。 <結果1> mysql> call logger('ほげ', 'ホゲ'); Query OK, 1 row affected (0.01 sec) mysql> select * from PROCEDURE_LOG; +--------+--------+---------------------+ | NAME | QUERY | EXECUTE_DATE | +--------+--------+---------------------+ | ほげ | ホゲ | 2014-03-26 10:41:26 | +--------+--------+---------------------+ 1 row in set (0.00 sec) ですが、testというストアドファンクションから呼び出してみましたが、 以下の結果2の通り、失敗します。 <結果2> mysql> select test(); ERROR 1336 (0A000): Dynamic SQL is not allowed in stored function or trigger <test> BEGIN CALL logger('test','1'); RETURN CONCAT('END'); END 現在動作している環境では、どこでエラーが発生したかがわからず、 ロガーの処理をなんとしても実装したいのですが、 いろいろ試してみても、解決できませんでした。 ご教示のほど、よろしくお願いします。 <参考> http://treeapps.hatenablog.com/entry/20120106/p1 <ストアドプロシージャ作成SQL文(logger)> SET NAMES UTF8; delimiter // -- ログ出力 DROP PROCEDURE IF EXISTS logger// CREATE PROCEDURE logger( IN PROCEDURE_NAME TEXT, IN SQL_TEXT TEXT ) BEGIN DECLARE CNT INT; CREATE TABLE IF NOT EXISTS PROCEDURE_LOG ( NAME VARCHAR(64), QUERY TEXT, EXECUTE_DATE TIMESTAMP, KEY IDX1 (NAME, QUERY(64), EXECUTE_DATE) ) ENGINE=MYISAM DEFAULT CHARSET=UTF8; -- 古いログを削除 SELECT COUNT(*) INTO CNT FROM PROCEDURE_LOG; IF CNT >= 1000 THEN DELETE FROM PROCEDURE_LOG LIMIT 1; END IF; -- テーブルにログを記録 SET @sql = CONCAT('INSERT INTO PROCEDURE_LOG VALUES (', QUOTE(PROCEDURE_NAME), ',', QUOTE(SQL_TEXT), ', null)'); PREPARE stmt FROM @sql; EXECUTE stmt; END // delimiter ;

    • ベストアンサー
    • MySQL
  • postgresのストアドファンクションでエラーの

    postgresのストアドファンクションでエラーの拾い方を教えてください。 insertして重複したらアップデートに切り替えるというサンプルをよく見かけます。 DECLARE BEGIN insert文 RETURN TRUE; EXCEPTION WHEN unique_violation THEN update文 END; それと同じノリで、何かしらのエラーがあった時に、 『RETURN FALSE;』するか、もしくはエラーコードをそのまま拾って返すというようなサンプルが欲しいです。 DECLARE BEGIN 何かしらのSQL RETURN TRUE; EXCEPTION WHEN すべてのエラー THEN RETURN FALSE; END; DECLARE BEGIN 何かしらのSQL RETURN TRUE; EXCEPTION WHEN すべてのエラー THEN RETURN エラーコード; END;

  • PL/SQLでファンクション名に変数を使用するには

    PL/SQLでファンクションの呼出を行いたいと思っています。 そこでファンクション名を変数で指定したいと思っているのですがうまくいきません。 ファンクション FUNCTION Check ( pi_Syori_No   IN NUMBER,  -- 処理No. po_Function_Name OUT VARCHAR2  -- ファンクション名 ) RETURN BOOLEAN IS TYPE Test_List IS VARRAY(100) OF VARCHAR2(10) NOT NULL; TYPE FcNameList IS VARRAY(100) OF VARCHAR2(10) NOT NULL; MmsCheckList Test_List := Test_List('○','×'); FcNameCheckList FcNameList := FcNameList('Check','Check'); BEGIN IF MmsCheckList(pi_Syori_No) = '○' THEN po_Function_Name :=FcNameCheckList(pi_Syori_No); ELSE po_Function_Name :=NULL; END IF; RETURN TRUE; EXCEPTION WHEN OTHERS THEN RETURN FALSE; END Check; メイン CREATE OR REPLACE PROCEDURE Test ( po_Out OUT VARCHAR2 ) IS Modoriti BOOLEAN :=TRUE; F_Neme VARCHAR2(2000) :=NULL; BEGIN IF Check(1,F_Neme) = TRUE THEN Modoriti := F_Neme(2,F_Neme); END IF; EXCEPTION WHEN OTHERS THEN po_Out := 'エラー'; END Test; この状態で実行すると下記のエラーが出てしまいます。 [PLS-00222: この有効範囲内に、名前'F_Neme'の関数は存在しません。] ファンクション名に変数を使うのは無理なのでしょうか? よろしくお願いいたします。

  • ストアドプロシージャについて

    お世話になります。 SQLServseのストアドプロシージャで、あるテーブルのテストデータを100件ほど作成したいと思っています。 しかし、プロシージャを実行すると「プライマリキーが重複しています」とエラーが出ます。 テーブル内にはすでにCODE='0001'と'0101'の2件が存在します。そのため挿入開始コードは'0002'としたのですが・・・。まだ同じエラーが発生します。 テーブル名:MST_USER  CODE char(4) ←キー  KBN  char(2)  NAME varchar(40)  PASS varchar(10) 作成したプロシージャ CREATE PROCEDURE dbo.test_update_USER AS declare @count int declare @kbn int set @count = 2 set @kbn = 0 while 1 = 1 begin update MST_USER set CODE = right('0000' + ltrim(str@count)), 4), KBN = right('00' + ltrim(str(@kbn)), 2), NAME = 'test' + ltrim(str(@count)), PASS = 'test' + ltrim(str(@count)) set @count = @count + 1 if (@count > 100) break if (@kbn > 3) set @kbn = 0 else set @kbn = @kbn + 1 end GO 何か間違えているのか自分ではわからなくなっている状態です。 どなたかご指摘いただけると幸いです。