PLSQL 数组中的不同值
Distinct Values in Array in PLSQL
我想将 table 中列中的不同值存储到数组中。我收到以下错误。我怎样才能做到这一点?
select count(distinct(Name)) into n from table;
create or replace type array_type is varray(100) of varchar2(20);
for i in 1 .. n loop
name_array.extend;
select distinct(Name) into name_array(i) from table order by name asc;
end loop;
Error :
ORA-01422: exact fetch returns more than requested number of rows
Table :
您可以SELECT DISTINCT value BULK COLLECT INTO
获取不同的值并将它们存储到一个集合中。
尝试:
CREATE TABLE test_table (
name VARCHAR2(20),
city VARCHAR2(250)
);
INSERT INTO test_table (name, city) VALUES ('A', 'X');
INSERT INTO test_table (name, city) VALUES ('B', 'Y');
INSERT INTO test_table (name, city) VALUES ('A', 'Z');
INSERT INTO test_table (name, city) VALUES ('C', 'K');
INSERT INTO test_table (name, city) VALUES ('D', 'P');
INSERT INTO test_table (name, city) VALUES ('A', 'Q');
INSERT INTO test_table (name, city) VALUES ('D', 'R');
INSERT INTO test_table (name, city) VALUES ('C', 'S');
COMMIT;
CREATE OR REPLACE TYPE array_type IS VARRAY(100) OF VARCHAR2(20);
DECLARE
v_name_array array_type := array_type();
BEGIN
SELECT DISTINCT NAME
BULK COLLECT
INTO v_name_array
FROM test_table
ORDER BY NAME ASC;
-- Show resulting values in collection
FOR i IN 1 .. v_name_array.count
LOOP
dbms_output.put_line(v_name_array(i));
END LOOP;
END;
/
在你们讨论解决方案之前,我想在这里提几点
第 1 点:- 希望您理解错误 ORA-01422。
当您在其中使用 select 时,它总是期望获取一行,而您的示例显然不是这种情况
原因:exact fetch指定的数量小于返回的行数。
操作:重写查询或更改请求的行数
要点 2 :- 游标的用法
您一次使用同一个游标进行计数,第二次使用相同的游标进行抓取。为什么不能一次声明它而只使用它一次来循环和获取或使用 for 循环代替
例如 - for i in (select distinct(Name) from table order by name) loop
要点 3 :- 类型的用法
我建议在本地创建类型而不是在数据库中创建为对象,除非您想在许多地方重用它。忘记提请注意用于存储值的索引。我不质疑你为什么使用 "of varchar(20)" 但你可以考虑一下。
第 4 点:- 标准化
作为一个建议,考虑规范化数据库。如果您查看示例数据,您将意识到我们需要避免的冗余数据。
第 5 点:- 批量收集的用法
正如其中一个答案中提到的,最好将批量收集与集合一起使用,但是是的,如果您要处理的数据集不是很大,您可能不会进行批量收集,而只需使用简单的循环来放置数据放入其中。
最后,如果尝试使代码在您的情况下正确(假设我们在数据库中创建的类型),我将执行如下操作。
DECLARE
n NUMBER;
--local variable is also fine here for type in case you changed your mind not to create in db
--type array_type is varray(100) of varchar2(20);
name_array array_type := array_type();
idx NUMBER := 1;
BEGIN
-- default order is ASC , so we can omit the same in real query
FOR i IN (SELECT DISTINCT(NAME) NAME FROM teststack ORDER BY NAME)
LOOP
name_array.extend;
name_array(idx) := i.name;
idx := idx + 1;
END LOOP;
FOR i IN 1..name_array.count LOOP
dbms_output.put_line(name_array(i));
END LOOP;
END;
/
我想将 table 中列中的不同值存储到数组中。我收到以下错误。我怎样才能做到这一点?
select count(distinct(Name)) into n from table;
create or replace type array_type is varray(100) of varchar2(20);
for i in 1 .. n loop
name_array.extend;
select distinct(Name) into name_array(i) from table order by name asc;
end loop;
Error :
ORA-01422: exact fetch returns more than requested number of rows
Table :
您可以SELECT DISTINCT value BULK COLLECT INTO
获取不同的值并将它们存储到一个集合中。
尝试:
CREATE TABLE test_table (
name VARCHAR2(20),
city VARCHAR2(250)
);
INSERT INTO test_table (name, city) VALUES ('A', 'X');
INSERT INTO test_table (name, city) VALUES ('B', 'Y');
INSERT INTO test_table (name, city) VALUES ('A', 'Z');
INSERT INTO test_table (name, city) VALUES ('C', 'K');
INSERT INTO test_table (name, city) VALUES ('D', 'P');
INSERT INTO test_table (name, city) VALUES ('A', 'Q');
INSERT INTO test_table (name, city) VALUES ('D', 'R');
INSERT INTO test_table (name, city) VALUES ('C', 'S');
COMMIT;
CREATE OR REPLACE TYPE array_type IS VARRAY(100) OF VARCHAR2(20);
DECLARE
v_name_array array_type := array_type();
BEGIN
SELECT DISTINCT NAME
BULK COLLECT
INTO v_name_array
FROM test_table
ORDER BY NAME ASC;
-- Show resulting values in collection
FOR i IN 1 .. v_name_array.count
LOOP
dbms_output.put_line(v_name_array(i));
END LOOP;
END;
/
在你们讨论解决方案之前,我想在这里提几点
第 1 点:- 希望您理解错误 ORA-01422。
当您在其中使用 select 时,它总是期望获取一行,而您的示例显然不是这种情况
原因:exact fetch指定的数量小于返回的行数。
操作:重写查询或更改请求的行数
要点 2 :- 游标的用法
您一次使用同一个游标进行计数,第二次使用相同的游标进行抓取。为什么不能一次声明它而只使用它一次来循环和获取或使用 for 循环代替
例如 - for i in (select distinct(Name) from table order by name) loop
要点 3 :- 类型的用法
我建议在本地创建类型而不是在数据库中创建为对象,除非您想在许多地方重用它。忘记提请注意用于存储值的索引。我不质疑你为什么使用 "of varchar(20)" 但你可以考虑一下。
第 4 点:- 标准化
作为一个建议,考虑规范化数据库。如果您查看示例数据,您将意识到我们需要避免的冗余数据。
第 5 点:- 批量收集的用法
正如其中一个答案中提到的,最好将批量收集与集合一起使用,但是是的,如果您要处理的数据集不是很大,您可能不会进行批量收集,而只需使用简单的循环来放置数据放入其中。
最后,如果尝试使代码在您的情况下正确(假设我们在数据库中创建的类型),我将执行如下操作。
DECLARE
n NUMBER;
--local variable is also fine here for type in case you changed your mind not to create in db
--type array_type is varray(100) of varchar2(20);
name_array array_type := array_type();
idx NUMBER := 1;
BEGIN
-- default order is ASC , so we can omit the same in real query
FOR i IN (SELECT DISTINCT(NAME) NAME FROM teststack ORDER BY NAME)
LOOP
name_array.extend;
name_array(idx) := i.name;
idx := idx + 1;
END LOOP;
FOR i IN 1..name_array.count LOOP
dbms_output.put_line(name_array(i));
END LOOP;
END;
/