如何创建一个名称取自变量的新序列?
让我们看一下以下示例:
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
。
如何将变量的值放在序列定义中以使其起作用?
答案 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;
varchar(50)
因为数据类型毫无意义,如果输入更长的字符串,可能会导致问题。只需使用text
或varchar
。
您可以在声明时指定变量。更短,更便宜,更清洁。
您需要动态SQL,我使用format()
和%I
来正确地转义标识符。详细说明:
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