【发布时间】:2021-10-12 17:18:12
【问题描述】:
我正在尝试将一些 SQL 包装到 PLSQL 过程中,以便用户可以传递参数而不是手动编辑 WHERE 子句,这会使他们有可能破坏工作代码。我要移植的 SQL 代码嵌入在 PROCEDURE 中,但 INTO 子句除外。
我知道在 PLSQL 中为了选择行需要一个 INTO 子句。环顾四周后,我看到了一个示例,它创建了一个对象和表类型。我不想做的事情,对我来说似乎过于复杂。如果可能的话,我希望将所有内容都保留在该过程的本地。
我也愿意在 access_history 表上使用 BULK collect,如果这会是一种更有效的方法。
当我尝试创建下面的过程时它不起作用,这是我可以使用一些帮助和 PLSQL 专业知识来指导我以最佳方向生成所需数据的地方。
其次,有没有办法使用 DEFAULT 值来确定要检索的行数。
如果过程是这样调用的:
EXEC LAST_EMPLOYEE_HISTORY(1) 这意味着获取employee_id=1 的最后20(DEFAULT)行,其中20 是默认值。
如果过程是这样调用的:
EXEC LAST_EMPLOYEE_HISTORY(1, 50) 表示获取employee_id=1 的最后50 行。
在解释和帮助我解决问题方面的任何帮助和专业知识将不胜感激。提前感谢所有回答的人。
下面是我的测试用例。
ALTER SESSION SET NLS_DATE_FORMAT = 'MMDDYYYY HH24:MI:SS';
CREATE OR REPLACE TYPE access_history_obj AS OBJECT(
employee_id NUMBER(6),
first_name VARCHAR2(20),
last_name VARCHAR2(20),
card_num VARCHAR2(10),
location_id NUMBER(6),
location_name VARCHAR2(30),
access_date DATE
);
CREATE OR REPLACE TYPE access_history_table IS TABLE OF access_history_obj;
Create table employees(
employee_id NUMBER(6),
first_name VARCHAR2(20),
last_name VARCHAR2(20),
card_num VARCHAR2(10),
work_days VARCHAR2(7)
);
INSERT INTO employees (
employee_id,
first_name,
last_name,
card_num,
work_days
)
WITH names AS (
SELECT 1, 'John', 'Doe', 'D564311','YYYYYNN' FROM dual UNION ALL
SELECT 2, 'Justin', 'Case', 'C224311','YYYYYNN' FROM dual UNION ALL
SELECT 3, 'Mike', 'Jones', 'J288811','YYYYYNN' FROM dual UNION ALL
SELECT 4, 'Jane', 'Smith', 'S564661','YYYYYNN' FROM dual
) SELECT * FROM names;
CREATE TABLE locations AS
SELECT level AS location_id,
'Door ' || level AS location_name,
CASE round(dbms_random.value(1,3))
WHEN 1 THEN 'A'
WHEN 2 THEN 'T'
WHEN 3 THEN 'T'
END AS location_type
FROM dual
CONNECT BY level <= 5;
create table access_history(
seq_num integer GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
employee_id NUMBER(6),
card_num varchar2(10),
location_id number(4),
access_date date,
processed NUMBER(1) default 0
);
INSERT INTO access_history(
employee_id,
card_num,
location_id,
access_date
)
WITH rws AS (
SELECT 1,'J11111',2,TO_DATE('2021/08/15 08:30:25', 'YYYY/MM/DD HH24:MI:SS') FROM dual UNION ALL
SELECT 1,'J11111',3,TO_DATE('2021/08/15 18:30:35', 'YYYY/MM/DD HH24:MI:SS') FROM dual UNION ALL
SELECT 2,'E11111',2,TO_DATE('2021/08/15 11:20:35', 'YYYY/MM/DD HH24:MI:SS') FROM dual) SELECT * FROM rws;
CREATE OR REPLACE PROCEDURE LAST_EMPLOYEE_HISTORY(
p_employee_id IN NUMBER,
p_rws IN number)
AS
BEGIN
with rws as (
select e.employee_id,
e.first_name,
e.last_name,
e.card_num,
l.location_id,
l.location_name,
a.access_date,
row_number () over
(
partition by e.employee_id
order by a.access_date DESC
) rn
FROM employees e
JOIN access_history a ON a.employee_id = e.employee_id
JOIN locations l ON l.location_id = a.location_id
)
select employee_id,
first_name,
last_name,
card_num,
location_id,
location_name,
access_date INTO access_history_table
from rws
where
employee_id = p_employee_id AND
rn <= p_rws
order by employee_id, access_date desc;
END;
EXEC LAST_EMPLOYEE_HISTORY(1)
【问题讨论】:
-
您可以考虑使用table function 而不是过程。
-
@sticky bit 我不想插入行,我只需要为employee_id 选择最后一个N。我希望格式包含我在示例中指定的值
-
我很困惑...我对表函数的建议与
INSERTing 有什么关系?
标签: sql oracle stored-procedures plsql