我试图编写一个存储过程来转换这个:
|----------|----------|----------|----------|----------|
| 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 |
|----------|----------|业务规则如下:
对于TEST_DATA_SOVLP中的每一行
ESD值不是null,那么:- insert a row in TEMP with the values: `<ESD value>`, `E`
TD值不是null,那么:- If `IS_DB=0` => insert in TEMP the values: `<TD value>`, `S`
- If `IS_DB=1` => insert in TEMP the values: `<TD value>`, `H`
但我并没有得到任何接近我预期的东西:
问答:
谢谢
1.存储某些数据的表
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)
) 3. 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 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;发布于 2018-05-20 09:52:08
只要运行这个INSERT INTO,就不需要程序了。
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 Demo
发布于 2018-05-20 09:55:14
从您的业务规则来看,您只需使用两个插入即可完成此操作,如下所示:
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_set上“嵌入”条件,这是由您的过程中的游标给出的。
decode将is_db与1进行比较,如果匹配,则使用'H',否则使用'S' (so 2将给出与0相同的结果;但我认为您需要检查数据,因为您只为1或0定义了要给出什么)。
关于程序
我已经在https://livesql.oracle.com上测试过它,输出看起来很好:
10 E
20 H
30 E
40 E
50 E
60 H
70 H
75 E
100 H
80 H(该表包含所有的is_db = 1,请参阅您在问题中提供的插入)。
此外,还相应地填充了temp表。因此,问题无法复制,您的原始过程似乎运行良好,如预期的那样。
发布于 2018-05-20 08:36:02
好吧,我终于把下面的代码做对了,修改了嵌套的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;https://stackoverflow.com/questions/50432956
复制相似问题