Select 在 ORACLE 中计数 (*)
Select count(*) IN ORACLE
我正在尝试执行以下代码来更新表,但无法在 CNT
变量中获得 count(*)
结果。
请问我如何在更新前获取表格中的记录数?
执行以下代码时出现错误:
Error report - ORA-06502: PL/SQL: numeric or value error: character to number conversion error ORA-06512: at line 12 06502. 00000 - "PL/SQL: numeric or value error%s"
DECLARE
tname varchar(255);
sql1 VARCHAR2(2000);
CNT INTEGER;
CURSOR myCursor IS select table_name from user_tables where table_name like '%VTS';
BEGIN
OPEN myCursor;
LOOP
FETCH myCursor INTO tname;
EXIT WHEN myCursor%NOTFOUND;
BEGIN
CNT:= 'SELECT COUNT(*) FROM ' || tname || ' where rownum=1';
EXECUTE IMMEDIATE 'CNT';
DBMS_OUTPUT.put_line( 'Number of rows = : ' || CNT);
IF ( CNT ) > 0 THEN
SELECT column_name INTO sql1 FROM user_tab_cols WHERE table_name = tname AND table_name not in (select view_name from user_views) and data_type ='VARCHAR2' ;
sql1 := 'UPDATE ' || tname || ' SET '|| sql1 || '=''hello''';
EXECUTE IMMEDIATE sql1;
END IF;
END;
END LOOP;
CLOSE myCursor;
END;
您需要 execute immediate
with into 子句。
调整后的程序如下:
DECLARE
tname varchar(255);
sql1 VARCHAR2(2000);
sql2 VARCHAR2(1000);
CNT NUMBER;
CURSOR myCursor IS select table_name from user_tables where table_name like '%VTS';
BEGIN
OPEN myCursor;
LOOP
FETCH myCursor INTO tname;
EXIT WHEN myCursor%NOTFOUND;
BEGIN
sql2 := 'SELECT COUNT(*) FROM ' || tname;
EXECUTE IMMEDIATE sql2 INTO CNT;
DBMS_OUTPUT.put_line( 'Number of rows = : ' || CNT);
IF ( CNT ) > 0 THEN
SELECT column_name
INTO sql1
FROM user_tab_cols
WHERE table_name = tname
AND table_name not in (select view_name from user_views)
AND data_type = 'VARCHAR2';
sql1 := 'UPDATE ' || tname || ' SET '|| sql1 || '=''hello''';
DBMS_OUTPUT.put_line( 'sql');
END IF;
END;
END LOOP;
CLOSE myCursor;
END;
补充说明:
- 当您 select 只是 COUNT(*) 时,您不需要 rownum = 1。
- 您需要更好地命名变量。
动态计数逻辑可以写得更干净
declare
tname varchar(255);
count_sql varchar2(500);
begin
for r in (
select table_name, num_rows from user_tables -- where table_name like '%VTS'
)
loop
count_sql := 'select count(*) from ' || r.table_name || ' where rownum = 1';
execute immediate count_sql into r.num_rows;
dbms_output.put_line('Number of rows in '||r.table_name||' = '||r.num_rows);
end loop;
end;
在 Oracle HR 示例模式中,输出为
Number of rows in REGIONS = 1
Number of rows in COUNTRIES = 1
Number of rows in LOCATIONS = 1
Number of rows in DEPARTMENTS = 1
Number of rows in JOBS = 1
Number of rows in EMPLOYEES = 1
Number of rows in JOB_HISTORY = 1
关于更新每个 varchar2
列的部分更复杂,因为如果有多个 varchar2 列,您不能只获取每个 table 的 varchar2 列。例如,假设 table locations
有 street_address
、postal_code
、city
和 state_province
。您可以遍历 user_tab_columns 中的每一行并生成四个语句
update locations set street_address = 'hello'
update locations set postal_code = 'hello'
update locations set city = 'hello'
update locations set state_province = 'hello'
当然,当你真正想要的是
时,效率会非常低下
update locations
set street_address = 'hello'
, postal_code = 'hello'
, city = 'hello'
, state_province = 'hello'
你当然可以生成这个,但它更复杂。也许是这样的(我已经用 dbms_output.put_line
替换了 execute immediate
所以我可以预览生成的 SQL 而不执行它):
declare
tname varchar(255);
count_sql varchar2(500);
update_sql varchar2(500);
l_separator varchar2(2);
begin
for t in (
select table_name, num_rows from user_tables -- where table_name like '%VTS'
)
loop
count_sql := 'select count(*) from ' || t.table_name || ' where rownum = 1';
execute immediate count_sql into t.num_rows;
dbms_output.put_line('Number of rows in '||t.table_name||' = '||t.num_rows);
if t.num_rows > 0 then
update_sql := 'update '||t.table_name||' set ';
l_separator := '';
for c in (
select column_name
from user_tab_columns
where table_name = t.table_name
and table_name not in (select view_name from user_views)
and data_type = 'VARCHAR2'
and data_length > 4
)
loop
update_sql := update_sql || l_separator || c.column_name||' = ''hello''';
l_separator := ', ';
end loop;
--execute immediate update_sql;
dbms_output.put_line(update_sql);
end if;
end loop;
end;
这给了我:
Number of rows in REGIONS = 1
update REGIONS set REGION_NAME = 'hello'
Number of rows in COUNTRIES = 1
update COUNTRIES set COUNTRY_NAME = 'hello'
Number of rows in LOCATIONS = 1
update LOCATIONS set STREET_ADDRESS = 'hello', POSTAL_CODE = 'hello', CITY = 'hello', STATE_PROVINCE = 'hello'
Number of rows in DEPARTMENTS = 1
update DEPARTMENTS set DEPARTMENT_NAME = 'hello'
Number of rows in JOBS = 1
update JOBS set JOB_ID = 'hello', JOB_TITLE = 'hello'
Number of rows in EMPLOYEES = 1
update EMPLOYEES set FIRST_NAME = 'hello', LAST_NAME = 'hello', EMAIL = 'hello', PHONE_NUMBER = 'hello', JOB_ID = 'hello'
Number of rows in JOB_HISTORY = 1
update JOB_HISTORY set JOB_ID = 'hello'
我正在尝试执行以下代码来更新表,但无法在 CNT
变量中获得 count(*)
结果。
请问我如何在更新前获取表格中的记录数?
执行以下代码时出现错误:
Error report - ORA-06502: PL/SQL: numeric or value error: character to number conversion error ORA-06512: at line 12 06502. 00000 - "PL/SQL: numeric or value error%s"
DECLARE
tname varchar(255);
sql1 VARCHAR2(2000);
CNT INTEGER;
CURSOR myCursor IS select table_name from user_tables where table_name like '%VTS';
BEGIN
OPEN myCursor;
LOOP
FETCH myCursor INTO tname;
EXIT WHEN myCursor%NOTFOUND;
BEGIN
CNT:= 'SELECT COUNT(*) FROM ' || tname || ' where rownum=1';
EXECUTE IMMEDIATE 'CNT';
DBMS_OUTPUT.put_line( 'Number of rows = : ' || CNT);
IF ( CNT ) > 0 THEN
SELECT column_name INTO sql1 FROM user_tab_cols WHERE table_name = tname AND table_name not in (select view_name from user_views) and data_type ='VARCHAR2' ;
sql1 := 'UPDATE ' || tname || ' SET '|| sql1 || '=''hello''';
EXECUTE IMMEDIATE sql1;
END IF;
END;
END LOOP;
CLOSE myCursor;
END;
您需要 execute immediate
with into 子句。
调整后的程序如下:
DECLARE
tname varchar(255);
sql1 VARCHAR2(2000);
sql2 VARCHAR2(1000);
CNT NUMBER;
CURSOR myCursor IS select table_name from user_tables where table_name like '%VTS';
BEGIN
OPEN myCursor;
LOOP
FETCH myCursor INTO tname;
EXIT WHEN myCursor%NOTFOUND;
BEGIN
sql2 := 'SELECT COUNT(*) FROM ' || tname;
EXECUTE IMMEDIATE sql2 INTO CNT;
DBMS_OUTPUT.put_line( 'Number of rows = : ' || CNT);
IF ( CNT ) > 0 THEN
SELECT column_name
INTO sql1
FROM user_tab_cols
WHERE table_name = tname
AND table_name not in (select view_name from user_views)
AND data_type = 'VARCHAR2';
sql1 := 'UPDATE ' || tname || ' SET '|| sql1 || '=''hello''';
DBMS_OUTPUT.put_line( 'sql');
END IF;
END;
END LOOP;
CLOSE myCursor;
END;
补充说明:
- 当您 select 只是 COUNT(*) 时,您不需要 rownum = 1。
- 您需要更好地命名变量。
动态计数逻辑可以写得更干净
declare
tname varchar(255);
count_sql varchar2(500);
begin
for r in (
select table_name, num_rows from user_tables -- where table_name like '%VTS'
)
loop
count_sql := 'select count(*) from ' || r.table_name || ' where rownum = 1';
execute immediate count_sql into r.num_rows;
dbms_output.put_line('Number of rows in '||r.table_name||' = '||r.num_rows);
end loop;
end;
在 Oracle HR 示例模式中,输出为
Number of rows in REGIONS = 1
Number of rows in COUNTRIES = 1
Number of rows in LOCATIONS = 1
Number of rows in DEPARTMENTS = 1
Number of rows in JOBS = 1
Number of rows in EMPLOYEES = 1
Number of rows in JOB_HISTORY = 1
关于更新每个 varchar2
列的部分更复杂,因为如果有多个 varchar2 列,您不能只获取每个 table 的 varchar2 列。例如,假设 table locations
有 street_address
、postal_code
、city
和 state_province
。您可以遍历 user_tab_columns 中的每一行并生成四个语句
update locations set street_address = 'hello'
update locations set postal_code = 'hello'
update locations set city = 'hello'
update locations set state_province = 'hello'
当然,当你真正想要的是
时,效率会非常低下update locations
set street_address = 'hello'
, postal_code = 'hello'
, city = 'hello'
, state_province = 'hello'
你当然可以生成这个,但它更复杂。也许是这样的(我已经用 dbms_output.put_line
替换了 execute immediate
所以我可以预览生成的 SQL 而不执行它):
declare
tname varchar(255);
count_sql varchar2(500);
update_sql varchar2(500);
l_separator varchar2(2);
begin
for t in (
select table_name, num_rows from user_tables -- where table_name like '%VTS'
)
loop
count_sql := 'select count(*) from ' || t.table_name || ' where rownum = 1';
execute immediate count_sql into t.num_rows;
dbms_output.put_line('Number of rows in '||t.table_name||' = '||t.num_rows);
if t.num_rows > 0 then
update_sql := 'update '||t.table_name||' set ';
l_separator := '';
for c in (
select column_name
from user_tab_columns
where table_name = t.table_name
and table_name not in (select view_name from user_views)
and data_type = 'VARCHAR2'
and data_length > 4
)
loop
update_sql := update_sql || l_separator || c.column_name||' = ''hello''';
l_separator := ', ';
end loop;
--execute immediate update_sql;
dbms_output.put_line(update_sql);
end if;
end loop;
end;
这给了我:
Number of rows in REGIONS = 1
update REGIONS set REGION_NAME = 'hello'
Number of rows in COUNTRIES = 1
update COUNTRIES set COUNTRY_NAME = 'hello'
Number of rows in LOCATIONS = 1
update LOCATIONS set STREET_ADDRESS = 'hello', POSTAL_CODE = 'hello', CITY = 'hello', STATE_PROVINCE = 'hello'
Number of rows in DEPARTMENTS = 1
update DEPARTMENTS set DEPARTMENT_NAME = 'hello'
Number of rows in JOBS = 1
update JOBS set JOB_ID = 'hello', JOB_TITLE = 'hello'
Number of rows in EMPLOYEES = 1
update EMPLOYEES set FIRST_NAME = 'hello', LAST_NAME = 'hello', EMAIL = 'hello', PHONE_NUMBER = 'hello', JOB_ID = 'hello'
Number of rows in JOB_HISTORY = 1
update JOB_HISTORY set JOB_ID = 'hello'