困惑于如何正确使用%rowtype为许多表

时间:2015-05-05 15:46:10

标签: plsql cursor rowtype

我试图从其他几个表创建一个派生的国家/地区数据表。这些表看起来像这样:

Countries 
ID | Name

Country_demographics
ID | date | Population | urban_pop | birth_rate

country_financials
ID | date | GDP | GDP_per_capita

现在,我正试图用

创建一个新表
New_Table
ID | Name | date | population | urban_pop | birth_rate | gdp | gdp_per_capita

我有一个目前看起来像这样的存储过程:

CREATE OR REPLEACE PROCEDURE SP_COUNTRY (
chunkSize IN INT
) AS

    --create tables to hold IDs and stats
        TYPE idTable IS TABLE OF COUNTRIES.ID%TYPE;
        TYPE dateTable IS TABLE OF COUNTRY_DEMOGRAPHICS.EVALUATION_DATE%TYPE;
        TYPE totPopTable IS TABLE OF COUNTRY_DEMOGRAPHICS.POPULATION_TOTAL_COUNT%TYPE;
        TYPE urbanPopTable IS TABLE OF COUNTRY_DEMOGRAPHICS.POPULATION_URBAN_COUNT%TYPE;
        --constructors
        ids idTable;
        dates dateTable;
        totpop totPopTable;
        urbanpop urbanPopTable;


    --cursors
    CURSOR countryCur IS
      SELECT c.ID,cd.EVALUATION_DATE,cd.POPULATION_TOTAL_COUNT,cd.POPULATION_URBAN_COUNT
      FROM COUNTRIES c,COUNTRY_DEMOGRAPHICS cd
      WHERE c.id=cd.COUNTRY_ID
      ORDER BY ID,EVALUATION_DATE;

    BEGIN
      dbms_output.enable(999999);
      --open cursor
      OPEN countryCur;
      LOOP
        --fetch and bulk collect
        FETCH countryCur BULK COLLECT INTO ids,dates,totpop,urbanpop
        LIMIT chunkSize;
        --loop over collections
        FOR j in ids.FIRST..ids.LAST
        LOOP
          --populate record
          country.COUNTRY_ID := ids(j);
          country.EVALUATION_DATE := dates(j);
          country.POPULATION_TOTAL_COUNT := totpop(j);
          country.POPULATION_URBAN_COUNT := urbanpop(j);
          --update/insert table with record (much confusion here on how to update/insert and check if already exists in derived table..)
          UPDATE NEW_TABLE SET ROW = country WHERE COUNTRY_ID = ids(j);
          dbms_output.put_line('id: ' || country.COUNTRY_ID || '  date: ' || country.EVALUATION_DATE);
          dbms_output.put_line('     pop: ' || country.POPULATION_TOTAL_COUNT || '  urban: ' || country.POPULATION_URBAN_COUNT);
        END LOOP;
      END LOOP;
      --close cursor
      CLOSE countryCur;
    END;

如您所见,我为每个数据使用不同的表类型。然后我计划制作一个循环,然后在我的new_table中插入/更新。我认为必须有一个更好的方法来使用%rowtype,或者创建一个记录并插入记录?我不确定

1 个答案:

答案 0 :(得分:1)

除非我通过简化这一点而遗漏了某些内容,并假设cd.date和cf.date相等,否则这应该有效:

INSERT INTO NEW_TABLE (ID, Name, date, population, urban_pop, birth_rate, gdp, gdp_per_capita)
values
(select c.id, c.name, cd.date, 
        cd.population, cd.urban_pop, cd.birthrate,
        cf.gdp, cf.gdp_per_capita)
from Countries c, country_demographics cd, country_financials cf 
where c.id = cd.id
and   cd.id = cf.id);

编辑:根据主键是否存在,使用MERGE语句进行更新或插入:

MERGE INTO NEW_TABLE nt
    USING ( select c.id, c.name, cd.date, 
                   cd.population, cd.urban_pop, cd.birthrate,
                   cf.gdp, cf.gdp_per_capita
            from Countries c, country_demographics cd, country_financials cf 
            where c.id = cd.id
            and   cd.id = cf.id ) a
    ON (nt.id = a.id )
    WHEN MATCHED THEN 
      UPDATE SET nt.Name           = a.Name,
                 nt.date           = a.date,
                 nt.population     = a.population,
                 nt.urban_pop      = a.urban_pop,
                 nt.birth_rate     = a.birth_rate,
                 nt.gdp            = a.gdp,
                 nt.gdp_per_capita = a.gdp_per_capita
    WHEN NOT MATCHED THEN 
      INSERT (ID, Name, date, population, urban_pop, birth_rate, gdp, gdp_per_capita)
      VALUES (a.id, a.Name, a.date, a.population, a.urban_pop, a.birth_rate, a.gdp, a.gdp_per_capita);