数组循环中的 Oracle 查询 - 奇怪的结果
Oracle query in an array loop - weird result
我正在遍历数组并执行 insert/update。在循环中,我检查记录是否存在。如果没有,执行插入。如果是,则执行更新。 STRING_SPLIT_FNC 是一个包,它接受一个字符串并在分隔符 (~) 上将其拆分并将拆分的字符串存储在一个数组中。
DECLARE
service_name VARCHAR(50) := 'Service1';
service_version VARCHAR(10) := '2016';
i INTEGER;
record_count NUMBER;
TYPE T_ARRAY_OF_VARCHAR IS TABLE OF VARCHAR(2000) INDEX BY BINARY_INTEGER;
main_array T_ARRAY_OF_VARCHAR;
split_array STRING_SPLIT_FNC.T_ARRAY;
BEGIN
main_array(1) := '2014|2015|2016|~service.info~25500~NULL~1';
main_array(2) := '2014|2015|2016|2017~service.path~/mypath/myfolder/myfile.zip~0';
main_array(3) := '2014|2015|2016|2017|2018~service.date~Yes~NULL~1';
SELECT COUNT(SERVICE_ID) INTO record_count FROM TEST_SERVICE WHERE SERVICE_DESC = service_name AND SERVICE_VERSION = service_version;
IF record_count = 0 THEN
INSERT INTO TEST_SERVICE(SERVICE_ID, SERVICE_DESC, SERVICE_VERSION) VALUES (SERVICE_SEQ.nextval, service_name, service_version);
END IF;
SELECT SERVICE_ID INTO service_id FROM TEST_SERVICE WHERE SERVICE_DESC = service_name AND SERVICE_VERSION = service_version;
i := main_array.FIRST;
LOOP
record_count := 0;
split_array := STRING_SPLIT_FNC.SPLIT(main_array(i),'~');
IF (INSTR(split_array(1), service_version) > 0) THEN
DBMS_OUTPUT.PUT_LINE('Record count prior: ' || record_count || ' Service Id: ' || service_id || ' Config: ' || split_array(2));
SELECT COUNT(*) INTO record_count FROM TEST_REF_SERVICE_CONFIG WHERE SERVICE_ID = service_id AND CONFIG_NAME = split_array(2);
DBMS_OUTPUT.PUT_LINE('Record count after: ' || record_count || ' Service Id: ' || service_id || ' Config: ' || split_array(2));
IF record_count = 0 THEN
INSERT INTO TEST_REF_SERVICE_CONFIG (REF_CONFIG_ID, SERVICE_ID, CONFIG_NAME, DEFAULT_VALUE, ALLOW_OVERRIDE) VALUES (REF_SERVICE_CONFIG_SEQ.nextval, service_id, split_array(2), split_array(3), TO_NUMBER(split_array(5)));
DBMS_OUTPUT.PUT_LINE('Inserted Service: ' || service_name || '[' || service_version || '], Config: ' || split_array(2) || ' [' || split_array(3) || '], Override: ' || split_array(5));
ELSE
record_count := 0;
SELECT COUNT(REF_CONFIG_ID) INTO record_count FROM TEST_REF_SERVICE_CONFIG WHERE SERVICE_ID = service_id AND CONFIG_NAME = split_array(2) AND DEFAULT_VALUE = split_array(3);
IF record_count = 0 THEN
DBMS_OUTPUT.PUT_LINE('Record count after [in update part]: ' || record_count);
UPDATE TEST_REF_SERVICE_CONFIG SET DEFAULT_VALUE = split_array(3), ALLOW_OVERRIDE = split_array(5) WHERE SERVICE_ID = service_id AND CONFIG_NAME = split_array(2) AND DEFAULT_VALUE = split_array(3);
DBMS_OUTPUT.PUT_LINE('Updated Service: ' || service_name || '[' || service_version || '], Config: ' || split_array(2) || ' [' || split_array(3) || '], Override: ' || split_array(5));
ELSE
record_count := 0;
DBMS_OUTPUT.PUT_LINE('No insert or update performed. Service: ' || service_name || '[' || service_version || '], Config: ' || split_array(2) || ' [' || split_array(3) || '], Override: ' || split_array(5));
END IF;
END IF;
ELSE
DBMS_OUTPUT.PUT_LINE('Specified service/version not found ' || service_name || '[' || service_version || ']');
END IF;
i := main_array.NEXT(i);
EXIT WHEN i IS NULL;
END LOOP;
END;
假设TEST_REF_SERVICE_CONFIGtable中没有记录。
现在,让我们说我 运行 这对于 service_name = Service1 和 service_version = 2015。service_id 是 500。main_array 中的所有 3 个元素得到已插入。
现在,我 运行 for service_name = Service1 和 service_version = 2017。服务 ID 是 502。它应该只插入来自 main_array 的最后 2 条记录.
下面的查询 returns record_count = 1 应该是 0:
SELECT COUNT(*) INTO record_count FROM TEST_REF_SERVICE_CONFIG WHERE SERVICE_ID = service_id AND CONFIG_NAME = split_array(2);
当我 运行 单独查询时,我得到计数为 0。
SELECT COUNT(*) FROM TEST_REF_SERVICE_CONFIG WHERE SERVICE_ID = 502 AND CONFIG_NAME = 'service.path';
为什么循环中的查询在应该为 0 时返回计数为 1?我也试过:
DECLARE
config_name VARCHAR(250);
...
LOOP
record_count := 0;
split_array := STRING_SPLIT_FNC.SPLIT(main_array(i),'~');
IF (INSTR(split_array(1), service_version) > 0) THEN
config_name := split_array(3);
SELECT COUNT(*) INTO record_count FROM TEST_REF_SERVICE_CONFIG WHERE SERVICE_ID = service_id AND CONFIG_NAME = config_name;
现在我得到 record_count 为 121!!!
预先感谢您的帮助。
我认为这里发生的事情是因为您为变量选择了与 table 中的列相同的名称。
当您在查询中引用变量时,您应该在其前面加上 : 符号。
所以,与其这样做:
SELECT COUNT(*) INTO record_count FROM TEST_REF_SERVICE_CONFIG WHERE SERVICE_ID = service_id AND CONFIG_NAME = config_name;
你应该这样做:
SELECT COUNT(*) INTO record_count FROM TEST_REF_SERVICE_CONFIG WHERE SERVICE_ID = :service_id AND CONFIG_NAME = :config_name;
或者更好的是,对您的变量和列名使用不同的命名约定,使您的代码更具可读性。
您省略 : 前缀的结果是 Oracle 将其解释为 "give me all the records where the value of the SERVICE_ID column equals the value of the SERVICE_ID column ...",这将应用于所有记录。
我认为您可能遇到了别名问题。
WHERE **SERVICE_ID = service_id** AND CONFIG_NAME = split_array(2);
解决此问题的方法是将变量名更改为不同于列名。如果这是一个 PL/SQL 过程或函数,您可以在变量名称前加上过程或函数的名称前缀,但您不能在匿名块中这样做。
我正在遍历数组并执行 insert/update。在循环中,我检查记录是否存在。如果没有,执行插入。如果是,则执行更新。 STRING_SPLIT_FNC 是一个包,它接受一个字符串并在分隔符 (~) 上将其拆分并将拆分的字符串存储在一个数组中。
DECLARE
service_name VARCHAR(50) := 'Service1';
service_version VARCHAR(10) := '2016';
i INTEGER;
record_count NUMBER;
TYPE T_ARRAY_OF_VARCHAR IS TABLE OF VARCHAR(2000) INDEX BY BINARY_INTEGER;
main_array T_ARRAY_OF_VARCHAR;
split_array STRING_SPLIT_FNC.T_ARRAY;
BEGIN
main_array(1) := '2014|2015|2016|~service.info~25500~NULL~1';
main_array(2) := '2014|2015|2016|2017~service.path~/mypath/myfolder/myfile.zip~0';
main_array(3) := '2014|2015|2016|2017|2018~service.date~Yes~NULL~1';
SELECT COUNT(SERVICE_ID) INTO record_count FROM TEST_SERVICE WHERE SERVICE_DESC = service_name AND SERVICE_VERSION = service_version;
IF record_count = 0 THEN
INSERT INTO TEST_SERVICE(SERVICE_ID, SERVICE_DESC, SERVICE_VERSION) VALUES (SERVICE_SEQ.nextval, service_name, service_version);
END IF;
SELECT SERVICE_ID INTO service_id FROM TEST_SERVICE WHERE SERVICE_DESC = service_name AND SERVICE_VERSION = service_version;
i := main_array.FIRST;
LOOP
record_count := 0;
split_array := STRING_SPLIT_FNC.SPLIT(main_array(i),'~');
IF (INSTR(split_array(1), service_version) > 0) THEN
DBMS_OUTPUT.PUT_LINE('Record count prior: ' || record_count || ' Service Id: ' || service_id || ' Config: ' || split_array(2));
SELECT COUNT(*) INTO record_count FROM TEST_REF_SERVICE_CONFIG WHERE SERVICE_ID = service_id AND CONFIG_NAME = split_array(2);
DBMS_OUTPUT.PUT_LINE('Record count after: ' || record_count || ' Service Id: ' || service_id || ' Config: ' || split_array(2));
IF record_count = 0 THEN
INSERT INTO TEST_REF_SERVICE_CONFIG (REF_CONFIG_ID, SERVICE_ID, CONFIG_NAME, DEFAULT_VALUE, ALLOW_OVERRIDE) VALUES (REF_SERVICE_CONFIG_SEQ.nextval, service_id, split_array(2), split_array(3), TO_NUMBER(split_array(5)));
DBMS_OUTPUT.PUT_LINE('Inserted Service: ' || service_name || '[' || service_version || '], Config: ' || split_array(2) || ' [' || split_array(3) || '], Override: ' || split_array(5));
ELSE
record_count := 0;
SELECT COUNT(REF_CONFIG_ID) INTO record_count FROM TEST_REF_SERVICE_CONFIG WHERE SERVICE_ID = service_id AND CONFIG_NAME = split_array(2) AND DEFAULT_VALUE = split_array(3);
IF record_count = 0 THEN
DBMS_OUTPUT.PUT_LINE('Record count after [in update part]: ' || record_count);
UPDATE TEST_REF_SERVICE_CONFIG SET DEFAULT_VALUE = split_array(3), ALLOW_OVERRIDE = split_array(5) WHERE SERVICE_ID = service_id AND CONFIG_NAME = split_array(2) AND DEFAULT_VALUE = split_array(3);
DBMS_OUTPUT.PUT_LINE('Updated Service: ' || service_name || '[' || service_version || '], Config: ' || split_array(2) || ' [' || split_array(3) || '], Override: ' || split_array(5));
ELSE
record_count := 0;
DBMS_OUTPUT.PUT_LINE('No insert or update performed. Service: ' || service_name || '[' || service_version || '], Config: ' || split_array(2) || ' [' || split_array(3) || '], Override: ' || split_array(5));
END IF;
END IF;
ELSE
DBMS_OUTPUT.PUT_LINE('Specified service/version not found ' || service_name || '[' || service_version || ']');
END IF;
i := main_array.NEXT(i);
EXIT WHEN i IS NULL;
END LOOP;
END;
假设TEST_REF_SERVICE_CONFIGtable中没有记录。 现在,让我们说我 运行 这对于 service_name = Service1 和 service_version = 2015。service_id 是 500。main_array 中的所有 3 个元素得到已插入。
现在,我 运行 for service_name = Service1 和 service_version = 2017。服务 ID 是 502。它应该只插入来自 main_array 的最后 2 条记录.
下面的查询 returns record_count = 1 应该是 0:
SELECT COUNT(*) INTO record_count FROM TEST_REF_SERVICE_CONFIG WHERE SERVICE_ID = service_id AND CONFIG_NAME = split_array(2);
当我 运行 单独查询时,我得到计数为 0。
SELECT COUNT(*) FROM TEST_REF_SERVICE_CONFIG WHERE SERVICE_ID = 502 AND CONFIG_NAME = 'service.path';
为什么循环中的查询在应该为 0 时返回计数为 1?我也试过:
DECLARE
config_name VARCHAR(250);
...
LOOP
record_count := 0;
split_array := STRING_SPLIT_FNC.SPLIT(main_array(i),'~');
IF (INSTR(split_array(1), service_version) > 0) THEN
config_name := split_array(3);
SELECT COUNT(*) INTO record_count FROM TEST_REF_SERVICE_CONFIG WHERE SERVICE_ID = service_id AND CONFIG_NAME = config_name;
现在我得到 record_count 为 121!!! 预先感谢您的帮助。
我认为这里发生的事情是因为您为变量选择了与 table 中的列相同的名称。
当您在查询中引用变量时,您应该在其前面加上 : 符号。 所以,与其这样做:
SELECT COUNT(*) INTO record_count FROM TEST_REF_SERVICE_CONFIG WHERE SERVICE_ID = service_id AND CONFIG_NAME = config_name;
你应该这样做:
SELECT COUNT(*) INTO record_count FROM TEST_REF_SERVICE_CONFIG WHERE SERVICE_ID = :service_id AND CONFIG_NAME = :config_name;
或者更好的是,对您的变量和列名使用不同的命名约定,使您的代码更具可读性。
您省略 : 前缀的结果是 Oracle 将其解释为 "give me all the records where the value of the SERVICE_ID column equals the value of the SERVICE_ID column ...",这将应用于所有记录。
我认为您可能遇到了别名问题。
WHERE **SERVICE_ID = service_id** AND CONFIG_NAME = split_array(2);
解决此问题的方法是将变量名更改为不同于列名。如果这是一个 PL/SQL 过程或函数,您可以在变量名称前加上过程或函数的名称前缀,但您不能在匿名块中这样做。