我想通过psql在空数据库中加载一些SQL函数:
psql -d my_database -f fuctions.sql --set ON_ERROR_STOP=1
我使用--set ON_ERROR_STOP=1
,因为如果脚本包含错误,我希望psql失败。
functions.sql
的内容是:
CREATE or REPLACE FUNCTION test_function() RETURNS INT AS $$
SELECT id from test_table;
$$ LANGUAGE sql;
我的问题是,psql检查加载函数时是否存在test_table
,并因此错误而失败:
ERROR: relation "test_table" does not exist LINE 2: SELECT id from test_table;
但是我不希望psql检查表是否存在,因为我稍后会创建这个表。
以下解决方法可行,但我无法使用它们:
答案 0 :(得分:10)
您可以在创建函数之前将配置变量check_function_bodies
设置为false。
例如,即使test_table
不存在,也可以让您创建测试函数:
BEGIN;
SET LOCAL check_function_bodies TO FALSE;
CREATE or REPLACE FUNCTION test_function() RETURNS INT AS $$
SELECT id from test_table;
$$ LANGUAGE sql;
COMMIT;
文档:http://www.postgresql.org/docs/9.5/static/runtime-config-client.html#GUC-CHECK-FUNCTION-BODIES
答案 1 :(得分:4)
错误消息来自Postgres,而不是来自psql。
如果您无法首先创建表格(出于何种原因),您可以“伪造它直到您创建它”:创建一个具有匹配结构的临时表。您只需要匹配列名称和类型。对于您的示例函数:
CREATE TEMP TABLE test_table (id int);
然后CREATE FUNCTION
通过。不允许以后放弃桌子。 Postgres不保存函数体中代码的依赖关系。因此,您可以在创建函数后删除表。如果在删除临时表后调用该函数,则会出现错误。
稍后创建实际表后,该函数将正常工作。
据我所知,不可能。也许Postgres有一个编译时选项可以禁用它。 The manual advises to use PL/PgSQL for cases like yours:
注意: SQL函数的整个主体在任何之前都会被解析 执行。虽然SQL函数可以包含改变命令的命令 系统目录(例如
CREATE TABLE
),这些命令的效果 在解析后来的命令时,将无法看到 功能。因此,例如,如果打包到单个SQL中,CREATE TABLE foo (...); INSERT INTO foo VALUES(...);
将无法按预期工作 函数,,因为在解析foo
命令时INSERT
尚不存在。 建议在此使用PL / PgSQL而不是的SQL函数 情况类型。
大胆强调我的。
答案 2 :(得分:0)
你可以拆分你的sql文件,例如进入DDL,DML然后执行函数。
类似
文件1:
CREATE TABLE foo (
id int primary key,
data int);
file2的:
CREATE or REPLACE FUNCTION test_function() RETURNS INT AS $$
SELECT id from test_table;
$$ LANGUAGE sql;
....
然后调用类似
的psqlpsql -f file1
psql -f file2
psql -f ....