• ベストアンサー
  • すぐに回答を!

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

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 お恥ずかしいですがいくらコードを見てもどこが原因なのかわかりません。 申し訳ありませんがご教授お願いできませんでしょうか。 昨日から悩んでいます。 どうか助けて下さい、宜しくお願いします。

共感・応援の気持ちを伝えよう!

  • 回答数2
  • 閲覧数1411
  • ありがとう数1

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

  • ベストアンサー
  • 回答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)に入れられない」と怒られたわけです。 代入時にスペースをトリムすれば解決します。 それと、クリア時のダブルクォートが気になりましたが、コンパイルが通っているので、これは問題無いのでしょうね。

共感・感謝の気持ちを伝えよう!

質問者からのお礼

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

関連する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 --------------------------------

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

    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   ・   ・ 申し訳ありませんが宜しくお願いします。

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

    値をカンマ形式で変換するファンクションを作成しています。 ファンクションの内容は下記の通りです。 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をつけたりしましたがワーニングが解消する事はできませんでした。多分、私の記述がいけないような気がします。 すみませんがどのように記述すればいいのでしょうか。 ご教授いただけませんでしょうか。 宜しくお願いします。

その他の回答 (1)

  • 回答No.2

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

共感・感謝の気持ちを伝えよう!

関連するQ&A

  • 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の出力結果について

    現在、引数の値を元に下記のような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です。 再度、申し訳ありませんがアドバイス、宜しくお願いします。 では、失礼します。

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

    参考の通りに、ストアドプロシージャ作成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
  • テーブル名が可変の動的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);」 そもそもこれが実現できたとしてレスポンスが上がるものなのでしょうか?どちらにせよコードを整理する意味でもファンクションにはしたいのですが。。 宜しくお願い致します。

  • 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'の関数は存在しません。] ファンクション名に変数を使うのは無理なのでしょうか? よろしくお願いいたします。

  • PL/pgSQLの返り値の取得方法について

    now()の結果を返すだけの以下の2つのPL/pgSQLを試しに作りました。SQL1は正しく結果が返ってきますが、SQL2は結果が何も返ってきません。どなたか説明できる方、いらっしゃいますでしょうか。宜しくお願い致します。 ■SQL1 CREATE OR REPLACE FUNCTION select_now1() RETURNS date AS $$ DECLARE d_current DATE := NULL; BEGIN SELECT INTO d_current now(); RETURN d_current; END; $$ LANGUAGE PLpgSQL; ■結果1 select_now1 ------------- 2011-03-19 (1 行) ■SQL2 CREATE OR REPLACE FUNCTION select_now2(OUT d_current date) AS $$ DECLARE d_current DATE := NULL; BEGIN SELECT INTO d_current now(); END; $$ LANGUAGE PLpgSQL; ■結果2 select_now2 ------------- (1 行)

  • oracle ファンクションの実行

    oracleでファンクションを作成しております。 このファンクションをVisualBasicより実行しているのですが、 以下のエラーが出力される状況です。 ORA-06550: 行1、列8: PLS-00553: キャラクタ・セット名が認識されません。 ORA-06550: 行0、列0: どのように対処すれば良いか分らず、 どなたか分る方がいらっしゃればご教授頂けますと 幸いです。 ★作成したファンクション CREATE OR REPLACE FUNCTION HINODE.H_HND8010U ( p_in_yoyakuid in varchar2) RETURN varchar2 --********************************************************* --* □ プロシージャ名 --* H_HND8010U --********************************************************* IS vSum varchar2(10); BEGIN vSum := p_in_yoyakuid; RETURN vSum; END; /

  • ストアドファンクションを差し替えたい

    VIEW は、CREATE OR REPLACE VIEW のようにして差し替えることができますが、 ストアドファンクションは、このような差し替えには対応していないのでしょうか? 本番稼動しているデータベースのストアドファンクションを差し替えたい場合は、 BEGIN DROP FUNCTION CREATE FUNCTION COMMIT とすればよろしいでしょうか?

  • ストアドファンクションで

    ストアドファンクションで、複数の値を返すことはできないのでしょうか? 例えば、Oracleなら構造体のユーザ型の値を返したりできます。 versionは、5.1.28です。 よろしくお願いします。

  • ストアドファンクションについて

    最近SQL sarvarの勉強を始めた初心者です。 今、参考書を読みながらストアドファンクションを勉強してるんですが、 create function dbo.Fn_aaaaa (@dat datetime) returns char(14) as begin return cast(datepart(yyyy, @dat) as char(4)) + '年' + cast(datepart(mm, @dat) as char(2)) + '月' + cast(datepart(mm, @dat) as char(2)) + '日' + end という例題にある「returns char(14)」とはどういう意味なのかがよくわかりません。正直、戻り値という概念をしっかりと理解していない部分があり困っています。 本当に初歩的でもしかしたらSQLに関係のない質問かもしれませんがよろしければお教えください。