序列名称取自变量

时间:2014-09-19 11:09:36

标签: sql postgresql sequence plpgsql dynamic-sql

如何创建一个名称取自变量的新序列?

让我们看一下以下示例:

CREATE OR REPLACE FUNCTION get_value(_name_part character varying)
  RETURNS INTEGER AS
$BODY$
DECLARE
    result bigint;
    sequencename character varying(50);
BEGIN
    sequencename = CONCAT('constant_part_of_name_', _name_part);
    IF((SELECT CAST(COUNT(*) AS INTEGER) FROM pg_class
        WHERE relname LIKE sequencename) = 0)
    THEN
       CREATE SEQUENCE sequencename --here is the guy this is all about
       MINVALUE 6000000
       INCREMENT BY 1;
    END IF;
    SELECT nextval(sequencename) INTO result;
    RETURN result;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE

现在,让我们说我想要一个带有_name_part =' Whatever'的序列,所以我输入:

SELECT get_value('Whatever');

如果序列constant_part_of_name_Whatever不存在,我的函数应该创建它并获取一个值;如果它存在,它应该只取一个值。但是,我创建了序列constant_part_of_name_sequencename

如何将变量的值放在序列定义中以使其起作用?

3 个答案:

答案 0 :(得分:1)

目前接受的答案存在许多问题。最重要的是,它没有考虑架构

改为使用:

CREATE OR REPLACE FUNCTION get_value(_name_part text)
  RETURNS bigint AS
$func$
DECLARE
   _seq text  := 'constant_part_of_name_' || _name_part;
BEGIN

CASE (SELECT c.relkind = 'S'::"char"
      FROM   pg_namespace n
      JOIN   pg_class     c ON c.relnamespace = n.oid
      WHERE  n.nspname = current_schema()  -- or provide your schema!
      AND    c.relname = _seq)
WHEN TRUE THEN           -- sequence exists
    -- do nothing
WHEN FALSE THEN          -- not a sequence
   RAISE EXCEPTION '% is not a sequence!', _seq;
ELSE                     -- sequence does not exist, name is free
   EXECUTE format('CREATE SEQUENCE %I MINVALUE 6000000 INCREMENT BY 1', _seq);
END CASE;

RETURN nextval(_seq);

END
$func$  LANGUAGE plpgsql;

SQL Fiddle.

重点

  • concat()仅在涉及NULL值时才有用。我假设您不想通过NULL

  • VOLATILE是默认值,因此只是噪音。

  • 如果要在NULL输入上返回NULL,请添加STRICT

答案 1 :(得分:0)

试试这个。希望这对你有用。

CREATE OR REPLACE FUNCTION get_value(_name_part character varying) RETURNS INTEGER AS
$BODY$
DECLARE
    result bigint;
    sequencename character varying(50);
    v_sql character varying;
BEGIN
    sequencename = CONCAT('constant_part_of_name_', _name_part);
    IF((SELECT CAST(COUNT(*) AS INTEGER) FROM pg_class WHERE relname LIKE sequencename) = 0)
     THEN
     v_sql :=  'CREATE SEQUENCE '||sequencename||' 
       MINVALUE 6000000
       INCREMENT BY 1;';
       EXECUTE  v_sql;
    END IF;
    SELECT nextval(sequencename) INTO result ;
    RETURN result;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE

答案 2 :(得分:0)

CREATE OR REPLACE FUNCTION get_value(_name_part character varying) RETURNS INTEGER AS
$BODY$
DECLARE
    result bigint;
    sequencename character varying(50);
BEGIN
    sequencename = CONCAT('constant_part_of_name_', _name_part);
    IF  (select exists(SELECT relname FROM pg_class c WHERE c.relkind = 'S' and relname = ''''||sequencename||'''') = false )
    THEN
    execute 'CREATE SEQUENCE '||sequencename||'MINVALUE 6000000 INCREMENT BY 1';
    else
    END IF;
    execute 'SELECT nextval('''||sequencename||''')' INTO result;
    RETURN result;
END;
$BODY$
LANGUAGE plpgsql VOLATILE