kbk*_*bkb 2 postgresql psql scripting postgresql-9.5
我想创建一个脚本,该脚本将创建一些自定义命名架构并在其中创建一些表和函数。像这样:
文件example.sh
:
#!/bin/bash
# this is the only place I want to set the schema name
SCH="ex"
export SCH
export PGPASSWORD="*******"
PSQL="psql \
-X \
-U postgres \
-h localhost \
--single-transaction \
--echo-all \
--set SCH=$SCH \
--set ON_ERROR_STOP=on "
eval $PSQL "-f ./example.sql"
Run Code Online (Sandbox Code Playgroud)
文件example.sql
:
DROP SCHEMA IF EXISTS :SCH CASCADE;
CREATE SCHEMA :SCH;
CREATE TABLE :SCH.my_table
(
id SERIAL PRIMARY KEY,
my_col text
);
INSERT INTO :SCH.my_table (my_col) VALUES ('abc'), ('def');
CREATE OR REPLACE FUNCTION :SCH.getLast()
RETURNS text AS $$
SELECT my_col FROM :SCH.my_table ORDER BY id DESC LIMIT 1;
$$ LANGUAGE sql STABLE;
SELECT * FROM :SCH.getLast();
Run Code Online (Sandbox Code Playgroud)
它工作正常,直到:
CREATE OR REPLACE FUNCTION :SCH.getLast()
RETURNS text AS $$
SELECT my_col FROM :SCH.my_table ORDER BY id DESC LIMIT 1;
$$ LANGUAGE sql STABLE;
Run Code Online (Sandbox Code Playgroud)
由于函数体是一个文本常量,因此:SCH
不会被模式名称替换,我们会得到一个错误:
psql:./example.sql:16: ERROR: syntax error at or near ":"
LINE 3: SELECT my_col FROM :SCH.my_table ORDER BY id DESC LIMIT 1;
Run Code Online (Sandbox Code Playgroud)
有没有一种巧妙的方法让它发挥作用?
这可以通过以下方式完成,但似乎应该有一种更简单的方法:
CREATE OR REPLACE FUNCTION :SCH.makeFunction(schema_name text)
RETURNS VOID AS $body$
BEGIN
EXECUTE format('CREATE OR REPLACE FUNCTION %1$s.getLast()
RETURNS text AS $$
SELECT my_col FROM %1$s.my_table ORDER BY id DESC LIMIT 1;
$$ LANGUAGE sql STABLE;', schema_name);
END
$body$ LANGUAGE plpgsql VOLATILE;
SELECT :SCH.makeFunction(:'SCH');
Run Code Online (Sandbox Code Playgroud)
实现此目的的一种有趣方法是使用psql
变量来存储整个函数体,例如
\\set body \'$$SELECT 1$$\'\n\nCREATE FUNCTION bla() RETURNS integer LANGUAGE SQL AS :c;\n\nSELECT bla();\n bla \n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n 1\n
Run Code Online (Sandbox Code Playgroud)\n\n或者,您可以将整个定义传递到变量中,然后运行它:
\n\n\\set function \'CREATE FUNCTION bla() RETURNS integer LANGUAGE SQL AS $$SELECT 1;$$;\'\n\n:function\n\nSELECT bla();\n bla \n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n 1\n
Run Code Online (Sandbox Code Playgroud)\n\n那么,问题就是如何把body放入一个合适的变量中。
\n\n从psql
上面的 9.3 开始,有一个\\gset
命令可以解决这个问题。我们构建一个查询,生成函数体作为输出,然后将其分配给一个psql
变量,并像上面一样使用它(使用format()
):
SELECT format(\'CREATE OR REPLACE FUNCTION %1$s.getLast()\n RETURNS text AS $$\n SELECT my_col FROM %1$s.my_table ORDER BY id DESC LIMIT 1;\n $$ LANGUAGE sql STABLE;\', \'test\') AS function;\n\n\\gset\n\n:function\n
Run Code Online (Sandbox Code Playgroud)\n\n并做了。
\n 归档时间: |
|
查看次数: |
8826 次 |
最近记录: |