0

この機能を修正しようとしていますが、不可能です!! 1つの整数「var_id」を宣言し、最初のクエリの値をid_valに挿入します。nullの場合はタグ名がテーブルに挿入され、var_id =最後の挿入IDです。それ以外の場合は、最後の挿入を行います。

CREATE OR REPLACE FUNCTION public."InsertVideoTag"
(
  IN  in_idvideo  integer,
  IN  in_tagname  VARCHAR(25)      
)
RETURNS bigint AS
$$

DECLARE var_id bigint DEFAULT NULL;


SELECT var_id := IDTag FROM Tag WHERE TagName = in_tagname;


IF var_id IS NULL
THEN

INSERT INTO tag (   TagName )
VALUES( in_tagname );

var_id := SELECT CURRVAL(pg_get_serial_sequence('public.tag','idtag'));

END IF;

INSERT INTO video_has_tag 
(                 
  IDVideo,      
  IDTag             
)
VALUES 
(
  in_idvideo,                
  var_id             
);

SELECT CURRVAL(pg_get_serial_sequence('public.video','idvideo'));
$$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER;
4

4 に答える 4

1
  • ifステートメントは必要ありません。where句で十分です。
  • 現在の値を選択することは、戻り値として(または他のテーブルFKに入力するために)適切ではありません。最初の挿入後にバンプされた可能性があります。

DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;

CREATE TABLE tag
        ( idtag SERIAL NOT NULL PRIMARY KEY
        , tagname varchar
        );
CREATE TABLE video_has_tag
        ( idvideo INTEGER NOT NULL
        , idtag INTEGER NOT NULL REFERENCES tag (idtag)
        );

CREATE OR REPLACE FUNCTION tmp.insertvideotag
            ( in_idvideo  integer , in_tagname  VARCHAR  )
RETURNS bigint AS
$$

DECLARE var_id bigint DEFAULT NULL;

BEGIN

INSERT INTO tag (tagname )
SELECT in_tagname
WHERE NOT EXISTS (
        SELECT * FROM tag
        WHERE tagname = in_tagname
        );

INSERT INTO video_has_tag (idvideo,idtag)
SELECT in_idvideo, tg.idtag
FROM tag tg
WHERE tg.tagname = in_tagname
RETURNING idtag          
INTO var_id
        ;

RETURN var_id;
END;
$$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER;
SELECT insertvideotag(11, 'Eleven');
SELECT insertvideotag(12, 'Eleven');
SELECT insertvideotag(13, 'Thirteen');

SELECT tv.idvideo
        ,tv.idtag, tg.tagname
FROM video_has_tag tv
JOIN tag tg ON tg.idtag = tv.idtag
        ;

結果:

NOTICE:  CREATE TABLE will create implicit sequence "tag_idtag_seq" for serial column "tag.idtag"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "tag_pkey" for table "tag"
CREATE TABLE
CREATE TABLE
CREATE FUNCTION
 insertvideotag 
----------------
              1
(1 row)

 insertvideotag 
----------------
              2
(1 row)

 idvideo | idtag | tagname  
---------+-------+----------
      11 |     1 | Eleven
      12 |     1 | Eleven
      13 |     2 | Thirteen
(2 rows)
于 2013-01-30T17:15:26.610 に答える
1

関数は純粋な関数に変換できるSQLため、パフォーマンスが大幅に向上します。video_has_tagまた、同じ引数で複数回呼び出されると、現在の機能によってテーブルに重複するエントリが作成されることにも注意しました。関数をべき等に変更しました。

私が想定した最初のテーブル構造:

CREATE TABLE tag (
  idTag   serial,
  tagName text);
CREATE TABLE video_has_tag (
  idVideo integer,
  idTag   integer);

そして、関数自体:

CREATE OR REPLACE FUNCTION insVideoTag(in_idvideo integer, in_tagname text)
RETURNS integer STRICT AS $insVideoTag$

WITH
new_tag AS (
    INSERT INTO tag (tagName)
    SELECT $2
     WHERE NOT EXISTS (SELECT 1 FROM tag WHERE tagName = $2)
    RETURNING idTag, tagName
), tag_data AS (
    SELECT * FROM new_tag
    UNION
    SELECT idTag, tagName FROM tag
     WHERE tagName = $2
), new_target AS (
    INSERT INTO video_has_tag(idVideo, idTag)
    SELECT $1, td.idTag
      FROM tag_data td
     WHERE NOT EXISTS (SELECT 1 FROM video_has_tag
                        WHERE idVideo=$1 AND idTag=td.idTag)
    RETURNING idVideo, idTag
)
SELECT idVideo FROM (
    SELECT * FROM new_target
    UNION
    SELECT * FROM video_has_tag
     WHERE idVideo=$1 AND idTag=(SELECT idTag FROM tag_data)
) s;

$insVideoTag$ LANGUAGE sql;
于 2013-01-30T17:59:23.323 に答える
0
CREATE OR REPLACE FUNCTION public."InsertVideoTag"
(
  IN  in_idvideo  integer,
  IN  in_tagname  VARCHAR(25)      
)
RETURNS bigint AS
$$
DECLARE var_id bigint DEFAULT NULL;
begin
var_id := (select IDTag FROM Tag WHERE TagName = in_tagname);
IF var_id IS NULL
THEN
    INSERT INTO tag (   TagName )
    VALUES( in_tagname );
    var_id := (SELECT CURRVAL(pg_get_serial_sequence('public.tag','idtag')));
END IF;
INSERT INTO video_has_tag 
(                 
  IDVideo,      
  IDTag             
)
VALUES 
(
  in_idvideo,                
  var_id             
);
return (SELECT CURRVAL(pg_get_serial_sequence('public.video','idvideo')));
end;
$$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER;
于 2013-01-30T16:48:09.533 に答える
0

postgresでは小文字の列やテーブル名などを操作する方がはるかに簡単であることがわかったので、既存のコードにいくつかの変更を加えました。

CREATE OR REPLACE FUNCTION public."insertvideotag"
(
  IN  in_idvideo  integer,
  IN  in_tagname  VARCHAR(25)      
)
RETURNS bigint AS
$$

DECLARE var_id bigint DEFAULT NULL;

BEGIN
--SELECT var_id := IDTag FROM Tag WHERE TagName = in_tagname;
SELECT idtag into var_id FROM tag WHERE tagname = in_tagname;


IF var_id IS NULL
THEN

INSERT INTO tag (   TagName )
VALUES( in_tagname );

--var_id := SELECT CURRVAL(pg_get_serial_sequence('public.tag','idtag'));
SELECT CURRVAL(pg_get_serial_sequence('public.tag','idtag')) into var_id;

END IF;

INSERT INTO video_has_tag 
(                 
  idvideo,      
  idtag             
)
VALUES 
(
  in_idvideo,                
  var_id             
);

SELECT CURRVAL(pg_get_serial_sequence('public.video','idvideo'));
END
$$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER;

残りの潜在的な問題は、シーケンス名と、おそらくどの値を返したいかです。

于 2013-01-30T16:55:28.333 に答える