创建引用不存在的表或列的SQL函数(尚)

时间:2015-03-20 08:10:57

标签: postgresql plpgsql psql sql-function

我想通过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检查表是否存在,因为我稍后会创建这个表。

以下解决方法可行,但我无法使用它们:

  • 忽略错误。如果脚本包含例如sql语法错误,我希望psql退出时出错。
  • 使用plpgsql函数而不是sql。我当然可以,但简单的sql函数往往是最好的选择。
  • 首先创建表格。我的真实场景实际上比这个例子更复杂。

3 个答案:

答案 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不保存函数体中代码的依赖关系。因此,您可以在创建函数后删除表。如果在删除临时表后调用该函数,则会出现错误。

稍后创建实际表后,该函数将正常工作。

在创建时禁用SQL函数解析?

据我所知,不可能。也许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;
....

然后调用类似

的psql
psql -f file1 
psql -f file2
psql -f ....