我无法在 PostgreSQL 中编写正常的选择过程。我在 SQL Server 方面有很好的经验。但 Postgres 看起来完全是一个不同的星球。
有人能帮我如何在 Postgres 中写这个语句吗?
create proc procedurename @somedate date
begin
select * from sometable where date>= @somedate
end
Run Code Online (Sandbox Code Playgroud)
我可以像这样执行它
exec procedurename 2017-05-02
Run Code Online (Sandbox Code Playgroud)
我尝试编写一个存储过程,它返回一个带有类似内容的表
Create or replace function hrms.salary() returns table(
lastmodified timestamp without time zone ,
employeeid integer ,
insuranceno character varying ,
uanno character varying ,
basic integer ,
hra numeric ,
conveyence integer ,
fixedallowance integer ,
epf numeric ,
eps numeric ,
esic numeric ,
bankname character varying ,
ifsccode character varying ,
bankaccount character varying ,
totalsalary integer
) as
$Body$
Begin
with pivotchart as(
SELECT * FROM hrms.crosstab(
$$ SELECT employeeid,today,count(employeeid) as countid
FROM hrms.timesheet
where dated>='2017-09-01'
and dated< '2017-09-01'::timestamp+ '1 MONTH'::INTERVAL
group by employeeid,today $$,
$$ select distinct today
from hrms.timesheet $$
)as
finalresult(employeeid int,leave int,present int,absent int, holiday int)
),
groupedresults as(
select employeeid ,
sum(present) as present,
sum(absent) as absent,
sum(holiday) as holiday,
sum(leave) as leave
from pivotchart
group by employeeid
),
numberofdays as(
SELECT extract(day from DATE_TRUNC('month', now()::timestamptz) + '1 MONTH'::INTERVAL
- DATE_TRUNC('month', now()::timestamptz))::int as interval
),
joinsofvalue as(
select emp.firstname,
emp.lastname,
emp.fathername,
grp.employeeid,
grp.Present,
grp.HOLIDAY,
grp.ABSENT,
grp.LEAVE,
sal.basic as Totalbasic,
(sal.basic)/(select interval from numberofdays )* ((select interval from numberofdays)-(absent))as calculatedbasic,
sal.hra as totalHRA,
(sal.hra)/(select interval from numberofdays )* ((select interval from numberofdays)-(absent))as calculatedHRA,
sal.conveyence as totalconveyence,
(sal.conveyence)/(select interval from numberofdays )* ((select interval from numberofdays)-(absent))as calculatedconveyence,
sal.fixedallowance as totalfixedallowance,
(sal.fixedallowance)/(select interval from numberofdays )* ((select interval from numberofdays)-(absent))as calculatedFA,
sal.epf as totalemployeeprovidendfund,
(sal.epf)/(select interval from numberofdays )* ((select interval from numberofdays)-(absent))as calculatedEPF,
sal.eps as totalemployeepensionscheme,
(sal.eps)/(select interval from numberofdays )* ((select interval from numberofdays)-(absent))as calculatedEPS,
sal.esic as totalemployeestateinsurance,
(sal.esic)/(select interval from numberofdays )* ((select interval from numberofdays)-(absent))as calculatedESIC,
sal.totalsalary as GrossSalary,
(sal.totalsalary)/(select interval from numberofdays )* ((select interval from numberofdays)-(absent))as NETSalary
from (groupedresults as grp
right outer join
hrms.employee as emp
on
grp.employeeid = emp.employeeid)
left outer join
hrms.salarystructure as sal
on emp.employeeid=sal.employeeid
)
select * from joinsofvalue;
end;
$Body$
language plpgsql;
Run Code Online (Sandbox Code Playgroud)
它创建了一个没有任何问题的函数。
Query returned successfully with no result in 38 msec.
Run Code Online (Sandbox Code Playgroud)
但当我再次尝试查询它时。使用
select * from hrms.salary()
Run Code Online (Sandbox Code Playgroud)
它给了我一个错误说明
ERROR: column reference "employeeid" is ambiguous
LINE 14: select employeeid ,
^
DETAIL: It could refer to either a PL/pgSQL variable or a table column.
Run Code Online (Sandbox Code Playgroud)
没有文档可以解决这个问题,但我确信 with 语句之后的所有内容都可以正常工作。事实上,我已经创建了一个具有相同查询的视图并且它有效。但我需要包含一个参数,这就是我需要它的原因。
小智 5
Postgres 没有过程。您需要一个返回结果的函数:
create function some_function(p_somedate date)
returns setof sometable
as
$$
select *
from sometable
where date >= p_somedate;
$$
language sql;
Run Code Online (Sandbox Code Playgroud)
然后运行:
select *
from some_function(date '2017-11-01');
Run Code Online (Sandbox Code Playgroud)
显示真实代码后编辑:
您使用的language plpgsql函数与普通 SQL 函数不同(language sql如我的示例中所示)。
如手册中所述,如果 PL/pgSQL 函数想要返回结果,则需要使用返回查询。
一个普通的 SQL 函数可以简单地编写一条 SELECT 语句。
如果你想坚持使用 PL/pgSQL,你需要这样的东西:
create or replace function hrms.salary()
returns table(...) as
$Body$
Begin
RETURN QUERY
with pivotchart as(
...
),
groupedresults as (
....
),
numberofdays as(
...
),
joinsofvalue as(
...
)
select *
from joinsofvalue;
end;
$Body$
language plpgsql;
Run Code Online (Sandbox Code Playgroud)
普通 SQL 函数通常比使用RETURN QUERY.
在这种情况下,您没有BEGIN ... END,只需将查询放入函数体中并将语言更改为sql:
create or replace function hrms.salary()
returns table(...) as
$Body$
-- no BEGIN here, no RETURN QUERY required
-- just write the query
with pivotchart as(
...
),
groupedresults as (
....
),
numberofdays as(
...
),
joinsofvalue as(
...
)
select *
from joinsofvalue;
$Body$
language sql;
Run Code Online (Sandbox Code Playgroud)
至于你的错误:
错误:列引用“employeeid”不明确
详细信息准确地告诉您该错误的原因是什么:
详细信息:它可以引用 PL/pgSQL 变量或表列。
您有一个名为 的参数employeeid ,并且有一个名为 的列employeeid。在查询中:
groupedresults as (
select employeeid ,
sum(present) as present,
sum(absent) as absent,
sum(holiday) as holiday,
sum(leave) as leave
from pivotchart
group by employeeid
)
Run Code Online (Sandbox Code Playgroud)
employeeid可以引用表的列或参数。
有关名称解析的更多详细信息,请参阅手册
通常的命名约定(正如我在第一个示例中使用的那样)是在参数前添加一些前缀,这样就不会出现名称冲突。
您还可以在表的列名前面加上前缀,以避免名称冲突:
groupedresults as (
select p.employeeid ,
sum(p.present) as present,
sum(p.absent) as absent,
sum(p.holiday) as holiday,
sum(p.leave) as leave
from pivotchart as p
group by p.employeeid
)
Run Code Online (Sandbox Code Playgroud)
但通常最好使用与列名称不冲突的参数和变量名称。
| 归档时间: |
|
| 查看次数: |
30111 次 |
| 最近记录: |