我正在尝试将SQL Server存储函数转换为PostgreSQL存储函数,我在declare @table1 table
遇到一个语法错误
CREATE OR REPLACE FUNCTION ETL_GetBuildingDetailsByUserID ( p_nInstID numeric=0)
RETURNS Boolean
AS $$
declare @table1 table
(
nbuilding numeric(18, 0) NOT NULL,
sbuild_name varchar(50) NULL,
sclient_build_id varchar(50) NULL,
nbuilding_inst_id numeric(18, 0) NOT NULL,
ntemp_building_id numeric(18,0) NULL,
nno_of_floors numeric(18,0) NULL
)
declare v_strDeptIds text;
v_strSubDeptIds text;
BEGIN
v_strsql := 'SELECT building.*
FROM building
WHERE (building.nbuilding_inst_id = '|| cast(p_nInstID as varchar(1)) ||')
';
print v_strsql
v_strsql1 text;
v_strsql1 := v_strsql
Insert into @table1; execute sp_executesql; v_strsql1
select * from @table1;
Return true;
END;
$$ LANGUAGE plpgsql;
错误
ERROR: syntax error at or near "@"
LINE 4: declare @table1 table
有人可以告诉我我在做什么错吗?
答案 0 :(得分:1)
似乎您的函数实际上返回的是SELECT查询的结果,而不是布尔值,因此returns boolean
开头是错误的。
要返回结果,您需要将该函数声明为returns table()
。但是,您似乎只是从building
表返回行,因此可以将其定义为returns setof building
。
然后删除似乎完全不必要的无用的动态SQL。
在PL / pgSQL中没有表变量,在从该表返回结果之前将查询结果复制到一个表中似乎是不必要的步骤,只会减慢速度。在Postgres中,您只需返回查询结果,而无需将其存储在本地。
此外:与其将参数强制转换为函数内的其他类型,不如使用您期望的类型声明该参数。
因此PostgreSQL中该函数的简化版本为:
CREATE OR REPLACE FUNCTION ETL_GetBuildingDetailsByUserID ( p_nInstID text)
RETURNS setof building
AS $$
select building.*
from building
WHERE building.nbuilding_inst_id = p_nInstID
$$ LANGUAGE sql;
您可以像这样使用它:
select *
from ETL_GetBuildingDetailsByUserID ('42');
不相关,但是:对于存储不带小数点的值的列使用numeric(18,0)
是过大的。您应该将这些列定义为bigint
。比数字快得多,占用的空间也少。