Oracle存储过程和游标
我正在尝试编写一个存储过程来转换:Oracle存储过程和游标,oracle,plsql,oracle11g,Oracle,Plsql,Oracle11g,我正在尝试编写一个存储过程来转换: |----------|----------|----------|----------|----------| | ID | ESD | TD | IS_DB | TEST_SET | |----------|----------|----------|----------|----------| | 1 | 10 | 20 | 1 | 2 | |
|----------|----------|----------|----------|----------|
| ID | ESD | TD | IS_DB | TEST_SET |
|----------|----------|----------|----------|----------|
| 1 | 10 | 20 | 1 | 2 |
| 2 | 30 | (null) | 1 | 2 |
| 3 | 40 | (null) | 1 | 2 |
| 4 | 50 | 60 | 0 | 2 |
| 5 | (null) | 70 | 1 | 2 |
| 6 | 75 | 100 | 1 | 2 |
| 7 | (null) | 80 | 1 | 2 |
|----------|----------|----------|----------|----------|
为此:
|----------|----------|
| DT | FLAG |
|----------|----------|
| 10 | E |
| 20 | H |
| 30 | E |
| 40 | E |
| 50 | E |
| 60 | S |
| 70 | H |
| 75 | E |
| 80 | H |
| 100 | H |
|----------|----------|
业务规则是:
对于测试数据\u SOVLP
中的每一行:
ESD
值不是null
,则:
- 在TEMP中插入一行,其值为:
,E
TD
值不是null
,则:
- 如果
=>请在TEMP中插入以下值:为_DB=0
,S
- 如果
=>请在TEMP中插入以下值:为\u DB=1
,H
- 临时表中没有写入任何内容
- 控制台显示的值对我来说毫无意义: 20小时 10 E 20小时 10 E 20小时
CREATE TABLE "TEST_DATA_SOVLP"
( "ID" NUMBER,
"ESD" NUMBER,
"TD" NUMBER,
"IS_DB" NUMBER(1,0) DEFAULT 0,
"TEST_SET" NUMBER
)
INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, TD, IS_DB, TEST_SET) VALUES ('1', '10', '20', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, IS_DB, TEST_SET) VALUES ('2', '30', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, IS_DB, TEST_SET) VALUES ('3', '40', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, TD, IS_DB, TEST_SET) VALUES ('4', '50', '60', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, TD, IS_DB, TEST_SET) VALUES ('5', '70', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, TD, IS_DB,TEST_SET) VALUES ('6', '75', '100', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, TD, IS_DB, TEST_SET) VALUES ('7', '80', '1', '2');
一些数据
CREATE TABLE "TEST_DATA_SOVLP"
( "ID" NUMBER,
"ESD" NUMBER,
"TD" NUMBER,
"IS_DB" NUMBER(1,0) DEFAULT 0,
"TEST_SET" NUMBER
)
INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, TD, IS_DB, TEST_SET) VALUES ('1', '10', '20', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, IS_DB, TEST_SET) VALUES ('2', '30', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, IS_DB, TEST_SET) VALUES ('3', '40', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, TD, IS_DB, TEST_SET) VALUES ('4', '50', '60', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, TD, IS_DB, TEST_SET) VALUES ('5', '70', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, TD, IS_DB,TEST_SET) VALUES ('6', '75', '100', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, TD, IS_DB, TEST_SET) VALUES ('7', '80', '1', '2');
2。用于存储结果的表
CREATE TABLE "TEMP"
( "DT" NUMBER,
"FLAG" VARCHAR2(1 BYTE)
)
CREATE OR REPLACE PROCEDURE S_OVLP
AS
CURSOR cSH IS
SELECT ID, ESD, TD, IS_DB, TEST_SET
FROM TEST_DATA_SOVLP
WHERE TEST_SET = 2;
rec_csh cSH%ROWTYPE;
BEGIN
-- DBMS_UTILITY.EXEC_DDL_STATEMENT('TRUNCATE TABLE TEMP');
OPEN cSH;
LOOP
FETCH cSH INTO rec_csh;
EXIT WHEN cSH%NOTFOUND;
IF rec_csh.esd IS NOT NULL THEN
INSERT INTO TEMP VALUES (rec_csh.esd, 'E');
dbms_output.put_line(rec_csh.esd || ' E');
END IF;
IF rec_csh.td IS NOT NULL THEN
IF rec_csh.is_db = 1 THEN
INSERT INTO TEMP VALUES (rec_csh.td, 'H');
dbms_output.put_line(rec_csh.td || ' H');
ELSE
INSERT INTO TEMP VALUES (rec_csh.td, 'S');
dbms_output.put_line(rec_csh.td || ' S');
END IF;
END IF;
END LOOP;
CLOSE cSH;
END S_OVLP;
3。PL/SQL操作数据并存储结果
CREATE TABLE "TEMP"
( "DT" NUMBER,
"FLAG" VARCHAR2(1 BYTE)
)
CREATE OR REPLACE PROCEDURE S_OVLP
AS
CURSOR cSH IS
SELECT ID, ESD, TD, IS_DB, TEST_SET
FROM TEST_DATA_SOVLP
WHERE TEST_SET = 2;
rec_csh cSH%ROWTYPE;
BEGIN
-- DBMS_UTILITY.EXEC_DDL_STATEMENT('TRUNCATE TABLE TEMP');
OPEN cSH;
LOOP
FETCH cSH INTO rec_csh;
EXIT WHEN cSH%NOTFOUND;
IF rec_csh.esd IS NOT NULL THEN
INSERT INTO TEMP VALUES (rec_csh.esd, 'E');
dbms_output.put_line(rec_csh.esd || ' E');
END IF;
IF rec_csh.td IS NOT NULL THEN
IF rec_csh.is_db = 1 THEN
INSERT INTO TEMP VALUES (rec_csh.td, 'H');
dbms_output.put_line(rec_csh.td || ' H');
ELSE
INSERT INTO TEMP VALUES (rec_csh.td, 'S');
dbms_output.put_line(rec_csh.td || ' S');
END IF;
END IF;
END LOOP;
CLOSE cSH;
END S_OVLP;
好的,我最终通过下面的代码得到了正确的结果,更改了嵌套的IF语句。 但是我对PL/SQL的工作方式非常失望
CREATE OR REPLACE PROCEDURE S_OVLP
AS
CURSOR cSH IS
SELECT ID, ESD, TD, IS_DB, TEST_SET
FROM TEST_DATA_SOVLP
WHERE TEST_SET = 2;
rec_csh cSH%ROWTYPE;
BEGIN
DBMS_UTILITY.EXEC_DDL_STATEMENT('TRUNCATE TABLE TEMP');
OPEN cSH;
LOOP
FETCH cSH INTO rec_csh;
EXIT WHEN cSH%NOTFOUND;
IF rec_csh.esd IS NOT NULL THEN
INSERT INTO TEMP VALUES (rec_csh.esd, 'E');
dbms_output.put_line(rec_csh.esd || ' E');
END IF;
IF rec_csh.td IS NULL THEN
CONTINUE;
END IF;
IF rec_csh.is_db = 1 THEN
INSERT INTO TEMP VALUES (rec_csh.td, 'H');
dbms_output.put_line(rec_csh.td || ' H');
ELSE
INSERT INTO TEMP VALUES (rec_csh.td, 'S');
dbms_output.put_line(rec_csh.td || ' S');
END IF;
END LOOP;
CLOSE cSH;
END S_OVLP;
好的,我最终通过下面的代码得到了正确的结果,更改了嵌套的IF语句。 但是我对PL/SQL的工作方式非常失望
CREATE OR REPLACE PROCEDURE S_OVLP
AS
CURSOR cSH IS
SELECT ID, ESD, TD, IS_DB, TEST_SET
FROM TEST_DATA_SOVLP
WHERE TEST_SET = 2;
rec_csh cSH%ROWTYPE;
BEGIN
DBMS_UTILITY.EXEC_DDL_STATEMENT('TRUNCATE TABLE TEMP');
OPEN cSH;
LOOP
FETCH cSH INTO rec_csh;
EXIT WHEN cSH%NOTFOUND;
IF rec_csh.esd IS NOT NULL THEN
INSERT INTO TEMP VALUES (rec_csh.esd, 'E');
dbms_output.put_line(rec_csh.esd || ' E');
END IF;
IF rec_csh.td IS NULL THEN
CONTINUE;
END IF;
IF rec_csh.is_db = 1 THEN
INSERT INTO TEMP VALUES (rec_csh.td, 'H');
dbms_output.put_line(rec_csh.td || ' H');
ELSE
INSERT INTO TEMP VALUES (rec_csh.td, 'S');
dbms_output.put_line(rec_csh.td || ' S');
END IF;
END LOOP;
CLOSE cSH;
END S_OVLP;
只需在中运行此
插入,无需过程
INSERT INTO temp
SELECT esd,
'E'
FROM test_data_sovlp
WHERE esd IS NOT NULL
UNION ALL
SELECT td,
CASE is_db
WHEN 0 THEN 'S'
WHEN 1 THEN 'H'
END AS FLAG
FROM test_data_sovlp
WHERE td IS NOT NULL
只需运行此插入到
,无需过程
INSERT INTO temp
SELECT esd,
'E'
FROM test_data_sovlp
WHERE esd IS NOT NULL
UNION ALL
SELECT td,
CASE is_db
WHEN 0 THEN 'S'
WHEN 1 THEN 'H'
END AS FLAG
FROM test_data_sovlp
WHERE td IS NOT NULL
从您的业务规则来看,似乎只需插入两个插件即可完成,如下所示:
insert into temp
select esd, 'E' from TEST_DATA_SOVLP where test_set=2 and esd is not null;
insert into temp
select td, decode(is_db, 1, 'H', 'S') from TEST_DATA_SOVLP
where test_set=2 and td is not null;
除了在esd
和td
上的条件外,还选择了在test\u set
上“嵌入”条件,该条件由过程中的光标给出
INSERT INTO temp
SELECT esd,
'E'
FROM test_data_sovlp
WHERE esd IS NOT NULL
UNION ALL
SELECT td,
CASE is_db
WHEN 0 THEN 'S'
WHEN 1 THEN 'H'
END AS FLAG
FROM test_data_sovlp
WHERE td IS NOT NULL
decode
将is_db
与1进行比较,如果匹配,则使用'H'
,否则使用'S'
(因此2将给出与0相同的结果;但我认为您需要检查数据,因为您已经定义了仅为1或0提供的内容)
关于程序
我已经对其进行了测试,输出看起来很好:
10 E
20 H
30 E
40 E
50 E
60 H
70 H
75 E
100 H
80 H
(表中的所有都是_db=1
,请参见您在问题中给出的插入)
此外,相应地填充temp
表。因此,这个问题无法复制,而且您的原始过程似乎按照预期运行良好。从您的业务规则来看,似乎只需插入两个插件即可完成,如下所示:
insert into temp
select esd, 'E' from TEST_DATA_SOVLP where test_set=2 and esd is not null;
insert into temp
select td, decode(is_db, 1, 'H', 'S') from TEST_DATA_SOVLP
where test_set=2 and td is not null;
除了在esd
和td
上的条件外,还选择了在test\u set
上“嵌入”条件,该条件由过程中的光标给出
INSERT INTO temp
SELECT esd,
'E'
FROM test_data_sovlp
WHERE esd IS NOT NULL
UNION ALL
SELECT td,
CASE is_db
WHEN 0 THEN 'S'
WHEN 1 THEN 'H'
END AS FLAG
FROM test_data_sovlp
WHERE td IS NOT NULL
decode
将is_db
与1进行比较,如果匹配,则使用'H'
,否则使用'S'
(因此2将给出与0相同的结果;但我认为您需要检查数据,因为您已经定义了仅为1或0提供的内容)
关于程序
我已经对其进行了测试,输出看起来很好:
10 E
20 H
30 E
40 E
50 E
60 H
70 H
75 E
100 H
80 H
(表中的所有都是_db=1
,请参见您在问题中给出的插入)
此外,相应地填充temp
表。因此,问题无法复制,您的原始过程似乎与预期一样正常。应该完全相同。Oracle的哪个版本?可能是因为你错过了一次提交而什么也没看到吗?太多的if
条件和循环。不要使用此代码。编辑您的问题并解释获取temp
表记录所需的条件。切勿为样本数据添加图像,仅使用纯文本。可以编写一个插入select*
查询来实现这一点,这比循环和条件要有效得多。最后,不要因为编写代码的糟糕方式而责怪PL/SQL。似乎您还没有使用该语言最强大的功能。@KaushikNayak我认为即使没有pl也可以做到,只有两个(使用decode…)插入语句并从“源”表中进行适当选择…@ShinTakezou:您从哪里读到我说我希望使用pl/SQL完成此任务的?@KaushikNayak Nowhere,我只是对这段代码所带来的奇怪之处添加了一条评论——这是写给你的,因为你提醒了OP pl/sql有多强大,所以我在最后一句话之后补充说,在这种情况下,我认为他(OP)甚至不需要这种能力。应该是完全一样的。Oracle的哪个版本?可能是因为你错过了一次提交而什么也没看到吗?太多的if
条件和循环。不要使用此代码。编辑您的问题并解释获取temp
表记录所需的条件。切勿为样本数据添加图像,仅使用纯文本。可以编写一个插入select*
查询来实现这一点,这比循环和条件要有效得多。最后,不要因为编写代码的糟糕方式而责怪PL/SQL。似乎您还没有使用该语言最强大的功能。@KaushikNayak我认为即使没有pl也可以做到,只有两个(使用decode…)插入语句并从“源”表中进行适当选择…@ShinTakezou:您从哪里读到我说我希望使用pl/SQL完成此任务的?@KaushikNayak Nowhere,我只是对这段代码所带来的奇怪之处添加了一条评论——这是写给你的,因为你提醒了OP pl/sql有多强大,所以我按照上一句话补充说,在这种情况下,我认为他(OP)甚至不需要这种能力。这看起来不错。上vo