从循环中定义的表名中选择

时间:2018-10-03 19:14:02

标签: sql oracle plsql

我有2个数据库连接:ab,它们都共享相同的架构,但不一定共享相同的数据。我需要使用循环检查每个表的两个数据库的总行数,并比较它们的计数。 到目前为止,我尝试使用嵌套表集合:

DECLARE  
    TYPE nt_rows IS TABLE OF NUMBER;
    nt_rows1 nt_num := nt_num();
    nt_rows2 nt_num := nt_num();
    counter INT := 0;

    CURSOR c_tables1 IS 
        SELECT TABLE_NAME
        FROM ALL_TABLES
        WHERE OWNER IN ('a')
        ORDER BY TABLE_NAME ASC;

    CURSOR c_tables2 IS
        SELECT TABLE_NAME
        FROM ALL_TABLES
        WHERE OWNER IN ('b')
        ORDER BY TABLE_NAME ASC;

BEGIN块:遍历每个游标并将它们添加到每个数组

BEGIN
    FOR i IN c_tables1 LOOP  
        nt_rows1.extend;
        SELECT COUNT(*) FROM a.i.TABLE_NAME INTO nt_rows1(counter);
    END LOOP;

最后一行不起作用,其中'a'是数据库连接名称,而i是每个table_name的索引。 我也尝试过:

nt_rows1(counter) := SELECT COUNT(*) FROM a.i.TABLE_NAME;

它也不起作用,任何建议都值得赞赏。

1 个答案:

答案 0 :(得分:1)

如果要从名称为字符串(例如,局部变量或游标字段)的表中查询数据,因此在编译时未知,则将需要使用动态SQL。

尝试替换行

SELECT COUNT(*) FROM a.i.TABLE_NAME INTO nt_rows1(counter);

使用

EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM a.' || i.TABLE_NAME INTO nt_rows1(counter);

还请注意,您的代码没有递增counter变量。由于您将counter设置为0,并且0不是嵌套表中的有效索引,因此建议您在添加counter之前添加一行以递增--setup emailDomain table if OBJECT_ID('tempdb..#emailDomain') is not NULL drop table #emailDomain create table #emailDomain ( id int IDENTITY(1,1) PRIMARY KEY, domain varchar(50) not null ) insert into #emailDomain --id is automatic generated values('aol.com') ,('att.net') ,('comcast.net') ,('facebook.com') ,('gmail.com') ,('gmx.com') --setup allowedChar table if OBJECT_ID('tempdb..#allowedChar') is not NULL drop table #allowedChar create table #allowedChar( id int IDENTITY(1,1) PRIMARY KEY, aChar char(1) not null ) insert into #allowedChar values('a'),('b'),('c'),('d'),('e'),('f'),('g'),('h'),('i'),('j'),('k'),('l'),('m'),('n'),('o'),('p'),('q') ,('r'),('s'),('t'),('u'),('v'),('w'),('x'),('y'),('z'),('1'),('2'),('3'),('4'),('5'),('6'),('9'),('7'),('0'),('8') --setup allowedSpecialChar table if OBJECT_ID('tempdb..#allowedSpecialChar') is not NULL drop table #allowedSpecialChar create table #allowedSpecialChar( id int IDENTITY(1,1) PRIMARY KEY, asChar char(1) ) insert into #allowedSpecialChar VALUES('_'),('-'),('.') declare @countDomains as int = (select count(*) from #emailDomain) declare @countallowedChars as int = (select count(*) from #allowedChar) declare @countallowedSpecialChars as int = (select count(*) from #allowedSpecialChar); if OBJECT_ID('tempdb..#rowsWithRandomCharsNrs') is not NULL drop table #rowsWithRandomCharsNrs; --generate with recursion 50 rows, with an id and a random length for the e-mail address with baseRowsWithEmailLength as ( select 1 as idMail, round(RAND(CHECKSUM(NEWID())) * 60 + 1,0) as strLength union all select idMail + 1 as idMail, round(RAND(CHECKSUM(NEWID())) * 60 + 1,0) as strLength from baseRowsWithEmailLength where idMail < 50 ) --generate with recursion a random number (indexChar) for every char in the string, which is an id to join with the table allowedChar ,rowsWithRandomCharsNrs as( select idMail, strLength, 1 as idchar, round(RAND(CHECKSUM(NEWID())) * (@countallowedChars-1) +1,0) as indexChar from baseRowsWithEmailLength union all select idMail, strLength, idchar + 1 as idchar, round(RAND(CHECKSUM(NEWID())) *(@countallowedChars-1) +1,0) as indexChar from rowsWithRandomCharsNrs where idchar < strLength ) select * into #rowsWithRandomCharsNrs from rowsWithRandomCharsNrs SELECT idMail ,concat(left(mailRandStr, firstMailPartLength),aspc.asChar,RIGHT(mailRandStr, StrLength - firstMailPartLength), '@', ed.domain) as Mail FROM( SELECT idMail ,strLength ,firstMailPartLength ,mailRandStr --generate a random number to join a random Domain and specialchar ,round(RAND(CHECKSUM(NEWID())) * (@countDomains-1) +1,0) as idDomain ,round(RAND(CHECKSUM(NEWID())) * (@countallowedSpecialChars-1) +1,0) as idSpecialChar FROM ( SELECT DISTINCT idMail ,StrLength ,round(StrLength * 0.75,0) as firstMailPartLength --concat all chars to a single string via for xml path ,( select ''+ac.aChar from #rowsWithRandomCharsNrs sub join #allowedChar ac on sub.indexChar = ac.id where sub.idMail = m.idMail FOR XML PATH('') )as mailRandStr FROM #rowsWithRandomCharsNrs m ) sub )sub left join #emailDomain ed on sub.idDomain = ed.id left join #allowedSpecialChar aspc on sub.idSpecialChar = aspc.id 上面的行。