oracle 存储过程的一些血与泪的教训



create or replace
PROCEDURE p_saveIssuerCinemaAdd_param(sheetId IN varchar2,issuerCinemaAddIds IN clob)  Authid Current_User AS
--sheetId 任务id  issuerCinemaAddIds 按上传影院列表
str_split ty_tbl_str_split;--影厅ids
str_filmType filmType_array;--影片类型
l_str   varchar2(4000);
is_jpeg number(1) :=0;
is_mpeg number(1) :=0;
equipIdCount number(10) :=0;
certificateIdCount number(10) :=0;
con number(10) :=0;
join_sql varchar2(4000);
BEGIN
--通过issuerCinemaAddIds找到所有的影院
  --execute immediate 'create global temporary table temp_cinema(id varchar2(32),cinemaId varchar2(32)) on commit delete ROWS';--建立临时表
 -- execute immediate 'create global temporary table temp_theater(id varchar2(32),theaterId varchar2(32)) on commit delete ROWS';--建立临时表
--找到符合条件的所有影院
        str_split :=fn_split(issuerCinemaAddIds,',');
        -- dbms_output.put_line('str_split.count影厅个数'||str_split.count);
         if(str_split.count >0) then
            for y in 1..str_split.count loop
                join_sql :='insert into T_ISSUER_CINEMA(ID,ISSUER_SKDM_RANGE_INFO_SHEET,CIENMA,sn,STARTTIME) select sys_guid(),'||''''||sheetId||''''||',c.cinema_id,sys_guid(),sysdate from t_issuer_cinema_add cc,t_cinema c where 
                cc.id='||''''|| str_split(y).strValue||''''||' and cc.cinemaname=c.cinema and cc.cinemacode=c.cinema_code ';  
               dbms_output.put_line('T_ISSUER_CINEMA sql语句:'||join_sql);
              execute immediate join_sql;  
            --从t_issuer_cinema_add表里删除符合条件的记录
              join_sql :='delete from t_issuer_cinema_add cc where cc.id='||''''|| str_split(y).strValue||''''||'';
              execute immediate join_sql;
            end loop; 
          end if;
   --过滤影片类型  
    select count(*) into con from t_skdmsheet_filmtype where skdmsheetid=sheetId;
    if(con>0) then
         select filmtypeid bulk collect into str_filmType from t_skdmsheet_filmtype where skdmsheetid=sheetId;
         for y in 1..con loop
              if(str_filmType(con)='MPEG2') then
                is_mpeg :=1;
              end if;
              if(str_filmType(con)='JPEG2000') then
                  is_jpeg :=1;
              end if; 
               if(str_filmType(con)='IMAX') then
                is_jpeg :=1;
              end if;
         end loop;
        
    end if;
   --过滤影厅ID
        --影厅ids
              join_sql := 'insert into temp_theater(id,theaterId) 
              select sys_guid(),m.THEATER_ID from v_certificate_theater m,T_ISSUER_CINEMA c where m.CINEMA_ID=c.cienma  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and m.THEATER_ID in 
               (select theater_id from t_theater where theater_attribute in (select filmattribute from t_skdmsheet_attribute where skdmsheetid='||''''||sheetId||''''||')) group by m.THEATER_ID';
               dbms_output.put_line('theaterId_sql语句'||join_sql);
              execute immediate join_sql;   
              join_sql :='select count(*) from temp_theater';
              execute immediate join_sql into con;   
             dbms_output.put_line('符合条件的影厅个数:'||con);  
  --更新t_issuer_skdm_range_info_sheet
  if(is_jpeg=1) then
    if(is_mpeg=0) then--c.cienma  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||'
      join_sql :='select count(distinct(m.equip_id)) from v_certificate_theater m,temp_theater theater,T_ISSUER_CINEMA c where c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and  m.is_jpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
      execute immediate join_sql into equipIdCount;
     join_sql :='select count(distinct(vn.certificate_id)) from (select m.* from v_certificate_theater m,temp_theater theater,T_ISSUER_CINEMA c  where  c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and m.is_jpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))) vt,v_certificate_theater vn where vt.equip_id=vn.equip_id';
      execute immediate join_sql into certificateIdCount;
      dbms_output.put_line('设备ID'||equipIdCount);
      dbms_output.put_line('证书ID'||certificateIdCount);
      update t_issuer_skdm_range_info_sheet set EQUIP_NUM=nvl(EQUIP_NUM,0)+equipIdCount,CERTIFICATE_NUM=nvl(CERTIFICATE_NUM,0)+certificateIdCount where SHEET_ID=sheetId;
      --插入T_ISSUER_CINEMA_THEATER
      join_sql :='select count(*) from v_certificate_theater m,temp_theater theater ,T_ISSUER_CINEMA c where c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and m.is_jpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
      execute immediate join_sql into con;
       dbms_output.put_line('插入T_ISSUER_CINEMA_THEATER'||con||'条数据');
      join_sql :='insert into T_ISSUER_CINEMA_THEATER(ID,ISSUER_SKDM_RANGE_INFO_SHEET,ISSUER_CINEMA,ISSUER_THEATER,IFTHREEORTWO,ISSUERTYPE) select sys_guid(),'||''''||sheetId||''''||',m.cinema_id,m.theater_id,nvl(m.THEATER_ATTRIBUTE,0),4 from v_certificate_theater m,temp_theater theater ,T_ISSUER_CINEMA c where c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and m.is_jpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
      dbms_output.put_line('插入T_ISSUER_CINEMA_THEATER语句'||join_sql);
       execute immediate join_sql;
      join_sql :='insert into T_ISSUER_CINEMA_THEATER_PMP(ID,ISSUER_SKDM_RANGE_INFO_SHEET,ISSUER_CINEMA,ISSUER_THEATER,IFTHREEORTWO,ISSUERTYPE,certificateId,equipId) select sys_guid(),'||''''||sheetId||''''||',m.cinema_id,m.theater_id,nvl(m.THEATER_ATTRIBUTE,0),4,m.certificate_id,m.equip_id from v_certificate_theater m,temp_theater theater,T_ISSUER_CINEMA c where  c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and m.is_jpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
      dbms_output.put_line('插入T_ISSUER_CINEMA_THEATER_PMP语句'||join_sql);
      execute immediate join_sql;
      
    end if;
    if(is_mpeg=1) then
      join_sql :='select count(distinct(m.equip_id)) from v_certificate_theater m,temp_theater theater,T_ISSUER_CINEMA c where c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and  m.is_jpeg=1 and m.is_mpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
      execute immediate join_sql into equipIdCount;
      join_sql :='select count(distinct(vn.certificate_id)) from (select m.* from v_certificate_theater m,temp_theater theater,T_ISSUER_CINEMA c  where  c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and m.is_jpeg=1 and m.is_mpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))) vt,v_certificate_theater vn where vt.equip_id=vn.equip_id';
      execute immediate join_sql into certificateIdCount;
      dbms_output.put_line('设备ID'||equipIdCount);
      dbms_output.put_line('证书ID'||certificateIdCount);
      update t_issuer_skdm_range_info_sheet set EQUIP_NUM=nvl(EQUIP_NUM,0)+equipIdCount,CERTIFICATE_NUM=nvl(CERTIFICATE_NUM,0)+certificateIdCount where SHEET_ID=sheetId;
      --插入T_ISSUER_CINEMA_THEATER
      join_sql :='select count(*) from v_certificate_theater m,temp_theater theater ,T_ISSUER_CINEMA c where c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and m.is_jpeg=1 and is_mpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
      execute immediate join_sql into con;
     -- dbms_output.put_line('插入T_ISSUER_CINEMA'||con||'条数据');
    --  join_sql :='insert into T_ISSUER_CINEMA(ID,ISSUER_SKDM_RANGE_INFO_SHEET,CIENMA,sn,STARTTIME) select sys_guid(),'||''''||sheetId||''''||',m.cinema_id,sys_guid(),sysdate from v_certificate_theater m,temp_theater_cinema theater where m.is_jpeg=1 and m.is_mpeg=1 and m.theater_id=theater.theaterId  and m.cinema_id=theater.cinemaId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
     -- dbms_output.put_line('插入T_ISSUER_CINEMA语句'||join_sql);
     -- execute immediate join_sql;
     dbms_output.put_line('插入T_ISSUER_CINEMA_THEATER'||con||'条数据');
      join_sql :='insert into T_ISSUER_CINEMA_THEATER(ID,ISSUER_SKDM_RANGE_INFO_SHEET,ISSUER_CINEMA,ISSUER_THEATER,IFTHREEORTWO,ISSUERTYPE) select sys_guid(),'||''''||sheetId||''''||',m.cinema_id,m.theater_id,nvl(m.THEATER_ATTRIBUTE,0),4 from v_certificate_theater m,temp_theater theater ,T_ISSUER_CINEMA c where c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and m.is_jpeg=1 and is_mpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
      dbms_output.put_line('插入T_ISSUER_CINEMA_THEATER语句'||join_sql);
       execute immediate join_sql;
      join_sql :='insert into T_ISSUER_CINEMA_THEATER_PMP(ID,ISSUER_SKDM_RANGE_INFO_SHEET,ISSUER_CINEMA,ISSUER_THEATER,IFTHREEORTWO,ISSUERTYPE,certificateId,equipId) select sys_guid(),'||''''||sheetId||''''||',m.cinema_id,m.theater_id,nvl(m.THEATER_ATTRIBUTE,0),4,m.certificate_id,m.equip_id from v_certificate_theater m,temp_theater theater,T_ISSUER_CINEMA c where  c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and m.is_jpeg=1 and m.is_mpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
      dbms_output.put_line('插入T_ISSUER_CINEMA_THEATER_PMP语句'||join_sql);
      execute immediate join_sql;
  end if;    
  end if;
  if(is_jpeg=0) then
     if(is_mpeg=0) then
       null;
     end if;
    if(is_mpeg=1) then
      join_sql :='select count(distinct(m.equip_id)) from v_certificate_theater m,temp_theater theater,T_ISSUER_CINEMA c where c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and m.is_mpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
      execute immediate join_sql into equipIdCount;
      join_sql :='select count(distinct(vn.certificate_id)) from (select m.* from v_certificate_theater m,temp_theater theater,T_ISSUER_CINEMA c  where  c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and m.is_mpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))) vt,v_certificate_theater vn where vt.equip_id=vn.equip_id';
      execute immediate join_sql into certificateIdCount;
      dbms_output.put_line('设备ID'||equipIdCount);
      dbms_output.put_line('证书ID'||certificateIdCount);
      update t_issuer_skdm_range_info_sheet set EQUIP_NUM=nvl(EQUIP_NUM,0)+equipIdCount,CERTIFICATE_NUM=nvl(CERTIFICATE_NUM,0)+certificateIdCount where SHEET_ID=sheetId;
      --插入T_ISSUER_CINEMA_THEATER
      join_sql :='select count(*) from v_certificate_theater m,temp_theater theater ,T_ISSUER_CINEMA c where c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and is_mpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
      execute immediate join_sql into con;
     -- dbms_output.put_line('插入T_ISSUER_CINEMA'||con||'条数据');
    --  join_sql :='insert into T_ISSUER_CINEMA(ID,ISSUER_SKDM_RANGE_INFO_SHEET,CIENMA,sn,STARTTIME) select sys_guid(),'||''''||sheetId||''''||',m.cinema_id,sys_guid(),sysdate from v_certificate_theater m,temp_theater_cinema theater where m.is_jpeg=1 and m.is_mpeg=1 and m.theater_id=theater.theaterId  and m.cinema_id=theater.cinemaId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
     -- dbms_output.put_line('插入T_ISSUER_CINEMA语句'||join_sql);
     -- execute immediate join_sql;
     dbms_output.put_line('插入T_ISSUER_CINEMA_THEATER'||con||'条数据');
      join_sql :='insert into T_ISSUER_CINEMA_THEATER(ID,ISSUER_SKDM_RANGE_INFO_SHEET,ISSUER_CINEMA,ISSUER_THEATER,IFTHREEORTWO,ISSUERTYPE) select sys_guid(),'||''''||sheetId||''''||',m.cinema_id,m.theater_id,nvl(m.THEATER_ATTRIBUTE,0),4 from v_certificate_theater m,temp_theater theater ,T_ISSUER_CINEMA c where c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and is_mpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
      dbms_output.put_line('插入T_ISSUER_CINEMA_THEATER语句'||join_sql);
       execute immediate join_sql;
    join_sql :='insert into T_ISSUER_CINEMA_THEATER_PMP(ID,ISSUER_SKDM_RANGE_INFO_SHEET,ISSUER_CINEMA,ISSUER_THEATER,IFTHREEORTWO,ISSUERTYPE,certificateId,equipId) select sys_guid(),'||''''||sheetId||''''||',m.cinema_id,m.theater_id,nvl(m.THEATER_ATTRIBUTE,0),4,m.certificate_id,m.equip_id from v_certificate_theater m,temp_theater theater,T_ISSUER_CINEMA c where  c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and m.is_mpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
      dbms_output.put_line('插入T_ISSUER_CINEMA_THEATER_PMP语句'||join_sql);
      execute immediate join_sql;
  end if;    
  end if;
  commit;
 -- execute immediate 'drop table temp_cinema'; 
 -- execute immediate 'drop table temp_theater'; 
  exception 
    when others then
        l_str:=sqlerrm(sqlcode);
        dbms_output.put_line(l_str);
end p_saveIssuerCinemaAdd_param;

以上是实际的一个存储过程,为了方便理解,我使用上面的存储过程记录一下编写过程中的一些问题。

  •   存储过程的声明部分可以看到俩个自己定义的数据类型

str_split ty_tbl_str_split;--影厅ids
str_filmType filmType_array;--影片类型
oracle支持自定义数据类型以满足实际需要,下面展示上面俩个类型的定义sql
create or replace
type     t_array IS TABLE OF VARCHAR2(32) ;
定义了一个可变数组,数组元素是一个32字节的字符串类型
create or replace TYPE ty_row_str_split as object (strValue VARCHAR2 (4000));
定义了一个对象,对象有一个字符串属性

create or replace TYPE     ty_tbl_str_split IS TABLE OF ty_row_str_split;
定义一个可变数组,里面的元素是上面的自定义对象

  • 常见的错误

1:

join_sql :='select count(distinct(m.equip_id)) from v_certificate_theater m,temp_theater theater,T_ISSUER_CINEMA c where c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and  m.is_jpeg=1 and m.is_mpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))';
      execute immediate join_sql into equipIdCount;
如果使用动态拼接sql,
c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||'
id的拼接要记得加上‘’,不让回报“标识符过长的错误”(当然标识符过长还有可能是其他原因,比如字符长度超过了4000字节)

冒号的转义可以是‘’‘’或者char(39)

如果使用静态sql(确保table存在,否则编译不过去),直接写sheetId,运行时会自动加上冒号

   例如:

c.issuer_skdm_range_info_sheet=sheetId

2:

join_sql :='select count(distinct(m.equip_id)) from v_certificate_theater m,temp_theater theater,T_ISSUER_CINEMA c where c.cienma=m.cinema_id  and c.issuer_skdm_range_info_sheet='||''''||sheetId||''''||' and  m.is_jpeg=1 and m.is_mpeg=1 and m.theater_id=theater.theaterId and m.equip_id in (select equip_id from t_equip where equip_version_id in (select version_id from t_equip_version where equip_type in (select equiptypeid from t_skdmsheet_equiptype where skdmsheetid='||''''|| sheetId||''''||')))'
execute immediate join_sql into equipIdCount;
动态查询sql不要在拼接字符串的时候into,否则无法得到结果,现在还不知道为什么,有知道的可以分享一下。

静态sql:

select count(distinct(m.equip_id)) into con from v_certificate_theater
3:为了防止抛出没有查到数据(nodata)这样的错误,可以在使用select count(*) into con from table if con>0 then end if;来判断

4:存储过程里任何一个逻辑分支里面不允许出现没有语句的情况:

    例如:

if con>0 then 

end if;--这样写编译不通过
if con>0 then 
  null;
end if;--正确
5:
create or replace
PROCEDURE p_saveIssuerCinemaAdd_param(sheetId IN varchar2,issuerCinemaAddIds IN clob)
参数类型不用指明大小,as后面的声明里面需要指明大小
6:游标使用的例子:

create or replace
PROCEDURE saveSheetCinemaTheaters_old(sheetId IN varchar2,typeNum IN number)  Authid Current_User AS
--sheetId 任务id  typeNum 范围保存类型 1 地区 2 影院  3上传列表

dETCC_Sql varchar2(4000) := 'drop table temp_ETCC';
dquipId_sql varchar2(4000) := 'drop table temp_quipId'; 
dfilmType_sql varchar2(4000) := 'drop table temp_filmType';
dtheaterId_sql varchar2(4000) := 'drop table temp_theaterId';
join_sql varchar2(4000);

 CURSOR cur is
   --查询范围sheet信息
   select * from t_issuer_skdm_range_info_sheet t where t.sheet_id =sheetId;
   v cur%ROWTYPE;
BEGIN
  ETCC_sql :='create global temporary table temp_ETCC(id varchar2(32),certificateId varchar2(32),IS_JPEG number(1),IS_MPEG number(1),equipId varchar2(32),theaterId varchar2(32),cinemaId varchar2(32)) on commit preserve  ROWS';
  quipId_sql :='create global temporary table temp_quipId(id varchar2(32),equipId varchar2(32)) on commit preserve  ROWS';
  filmType_sql :='create global temporary table temp_filmType(id varchar2(32),IS_JPEG number(1),IS_MPEG number(1)) on commit preserve  ROWS';
  theaterId_sql :='create global temporary table temp_theaterId(id varchar2(32),theaterId varchar2(32)) on commit preserve  ROWS';
 
   --过滤影片类型
    select count(*) into con from t_skdmsheet_filmtype where skdmsheetid=sheetId;
    if(con>0) then
         select filmtypeid bulk collect into str_filmType from t_skdmsheet_filmtype where skdmsheetid=sheetId;
         for y in 1..con loop
              if(str_filmType(con)='MPEG2') then
                is_mpeg :=1;
              end if;
              if(str_filmType(con)='JPEG2000') then
                  is_jpeg :=1;
              end if; 
               if(str_filmType(con)='IMAX') then
                is_jpeg :=1;
              end if;
         end loop;
    end if;
   --过滤影厅ID
  OPEN cur;
     LOOP
       BEGIN
         fetch cur into v;
         exit when cur%notfound;
        --影厅ids
         str_split :=fn_split( v.equip_info,',');
         dbms_output.put_line('str_split.count影厅个数'||str_split.count);
         if(str_split.count >0) then
            for y in 1..str_split.count loop
                join_sql := 'insert into temp_theaterId(id,theaterId) select sys_guid(),theater_id from t_theater where theater_id='||''''|| str_split(y).strValue||''''||' and theater_attribute in 
               (select filmattribute from t_skdmsheet_attribute where skdmsheetid='||''''||sheetId||''''||')';
               dbms_output.put_line('theaterId_sql'||join_sql);
              execute immediate join_sql;
               -- insert into temp_theaterId(id,theaterId) 
                --select sys_guid(),theater_id from t_theater 
                   -- where theater_id=str_split(y).strValue and theater_attribute in 
                       --(select filmattribute from t_skdmsheet_attribute where skdmsheetid=sheetId);
            end loop;
         end if;
         exception 
            when others then
                l_str:=sqlerrm(sqlcode);
                dbms_output.put_line(l_str);
       end;
     END LOOP;
  CLOSE cur;
   exception 
    when others then
        l_str:=sqlerrm(sqlcode);
        dbms_output.put_line(l_str);
end saveSheetCinemaTheaters_old;

7:
 select filmtypeid bulk collect into str_filmType from t_skdmsheet_filmtype where skdmsheetid=sheetId;
bulk collect
将查询出来的字段放入数组中

8:临时表杂谈

 说到临时表,顺便提一下静态sql跟动态sql的区别,以及oracle的临时表创建与使用不同于其他厂商的数据库

(1):动态sql与静态sql

首先,所谓SQL的动态和静态,是指SQL语句在何时被编译和执行,二者都是用在SQL嵌入式编程中的,这里所说的嵌入式是指将SQL语句嵌入在高级语言中,而不是针对于单片机的那种嵌入式编程。
在某种高级语言中,如果嵌入了SQL语句,而这个SQL语句的主体结构已经明确,例如在Java的一段代码中有一个待执行的SQL“select * from t1 where c1>5”,在Java编译阶段,就可以将这段SQL交给数据库管理系统去分析,数据库软件可以对这段SQL进行语法解析,生成数据库方面的可执行代码,这样的SQL称为静态SQL,即在编译阶段就可以确定数据库要做什么事情。
而如果嵌入的SQL没有明确给出,如在Java中定义了一个字符串类型的变量sql:String sql;,然后采用preparedStatement对象的execute方法去执行这个sql,该sql的值可能等于从文本框中读取的一个SQL或者从键盘输入的SQL,但具体是什么,在编译时无法确定,只有等到程序运行起来,在执行的过程中才能确定,这种SQL叫做动态SQL。例如每一种数据库软件都有能够执行SQL语句的界面,那个界面接收的SQL就是动态SQL,因为数据库厂商在做这个界面时,并不知道用户会输入哪些SQL,只有在该界面执行后,接收了用户的实际输入,才知道SQL是什么。
另外还要注意一点,在SQL中如果某些参数没有确定,如"select * from t1 where c1>? and c2<?",这种语句是静态SQL,不是动态SQL,虽然个别参数的值不知道,但整个SQL的结构已经确定,数据库是可以将它编译的,在执行阶段只需将个别参数的值补充进来即可。
(2)oracle中
execute immediate
其他数据库写法有可能不一样,意思一样
<pre id="best-content-809948816" class="best-text mb-10">简单来说 就是你一个存储过程当中 创建了一个表 table_a 然后要用insert into将其他的数据插入到这个table_a当中,但是因为你在创建过程的时候 table_a还不存在,过程就会显示有编译错误,因为table_a不存在必然导致过程无法执行,所以无法编译成功,而把insert into语句加如到 execute immediate之后 则oracle不会再去理会这个对象是否存在,因此可以成功编译和执行

 

(3):临时表

有一个问题重点说明,很简单但很容易忽略:如果你存储过程中使用到多个临时表,而且是事务级别的临时表,一定要在存储过程结束时再提交,不要在中途结束一个事务(切记:DDL操作自动提交事务,所以最好刚开始将所有用到的临时表一次性建好,防止中途建立另一张时隐性commit,把前面临时表的数据删除)。

<p style="background:rgb(255,252,246);">原表和临时表的共享操作不一样。一般来说,临时表只有你一个线程在用,没有任何用户、线程和你竞争使用该临时表。而原表总是有不同的用户、不同的线程在共享使用,对查询响最大的是有大量的数据在写入或者频繁的写入,那么查询的时候就会涉及到很多事务机制(并发、锁)的问题,产生了不同类型的等待事件,所以慢。相比较临时表就没有并发,只要服务器配置好,就非常快。</p><p style="background:rgb(255,252,246);"><span style="background:rgb(255,252,246);">虽然插入语句好像也包含了查询,可是其并不将查询结果返回,只是在数据库中直接打包做了复制而已,所以查询结果集越大,耗时差异越明显。</span></p><p style="background:rgb(255,252,246);">两个数据库临时表实现方式的异同:

  <span style="font-family:Times New Roman;">SQL SERVER</span><span style="font-family:宋体;">临时表跟</span><span style="font-family:Times New Roman;">ORACLE</span><span style="font-family:宋体;">数据库临时表的差异,可以利用一句话来概括。</span><span style="font-family:Times New Roman;">SQL SERVER </span><span style="font-family:宋体;">临时表是在需要用到的时候创建</span><span style="font-family:Times New Roman;">; </span><span style="font-family:宋体;">而</span><span style="font-family:Times New Roman;">ORACLE </span><span style="font-family:宋体;">数据库的临时表,则是在数据库初始化中就开始创建,在具体的会话或者事务开始后进行操作,结束一个会话或者结束一个事务后该数据库的内容就会被清空。具体情况要看你建的是会话级别的临时表还是事务级别的临时表</span></p><p style="background:rgb(255,252,246);"><span style="color:#ff00;"></span><pre name="code" class="html">create global temporary table temp_cinema(id varchar2(32),cinemaId varchar2(32)) on commit delete ROWS --事务级别临时表,<span style="color:#ff00;">结束一个事务delete到所有数据</span>

在创建时的异同。

  SQL SERVER 数据库的临时表,是在实际需要时创建的。具体的来说,可以利用SELECT语句与CREAT语句创建临时表。如可以利用SELECT * INTO #USER_TEMP FROM USER; 通过这条语句就可以在需要的时间创建一张临时表。除此之外,还可以利用CREATE语句,在需要的时候创建临时表。

  而ORACLE数据库,是在数据库系统初始化的过程中,就需要建立临时表。也就是在用户安装财务管理软件系统时,初始化数据库系统时,系统就会创建临时表。而不是在临时表需要用到的时候,才被创建。故,ORACLE数据库的临时表创建方式只有一种,在数据库初始化的时候,利用CREATE创建数据库临时表。所以,ORACLE数据库临时表,又有另一种说法。我们一般称ORACLE数据库的临时表是永久性的,只是临时表的内容是临时的,在需要用到临时表时,只要直接调用即可,而不用临时创建。这不像SQL SERVER数据库那样,只有在用到时,才创建该临时表当结束会话时,不仅表中的数据被清空了,而且该表也被删除了。

SQL SERVER在结束一个会话后,就会把用户所创建的临时表删除。而ORACLE在结束一个会话或者一个事务时,删除的只是表的内容,表的结构仍然会存在。ORACLE就是凭借牺牲一点表结构的存储空间,来达到提高ORACLE 数据库临时表处理性能的目的。

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

 SQL SERVER数据库系统有两种临时表,一种是本地临时表,一种是全局临时表。本地临时表只在当前会话中可以查找到。也就是说,某个用户创建了一个临时表,只有本人可以查询得到,而其他用户是查询不到这张临时表的。第二种是全局临时表,这张表无论是谁创建的,只要该表的会话没有结束,即该临时表只要存在与数据库中,则任何登陆该数据库的用户都可以查询到该临时表的内容。无论是采取哪种表,只要创建该临时表的用户结束该对话时,则该表就会被自动删除。如要实现上面所讲的用户帐户重复登陆的问题,需要用到全局临时表。当一个系统用户登陆时,就新建一张以该用户名命名的临时表当另外一个用户也试图想以这个用户名登陆时,系统就会查到以该用户名为名字的临时表已经存在,如此,就会拒绝该用户名的再次登陆。而当该用户退出时,或者意外中断该会话时,则该临时表就会被系统删除。该帐户名下次登陆时,就可以正常使用。

  ORACLE数据库系统的临时表也有两种,一种是事务型临时表,一种是会话型临时表。事物型临时表是当一个事物结束时清空临时表的内容而会话型临时表就当一个会话中断或者被重新连接时数据表的内容就会清空了。从中,我们可以看到在数据清空方面,两个数据库处理方式的两个重大区别。一是ORACLE 数据库在清除临时表是,只清楚数据,而不清楚临时表的本身。二是从功能上来讲,ORACLE还提供了一种更加细分的事务型临时表。一个会话中,可能有多个事务。也就是说,ORACLE 清空临时型数据表的时间更加细腻,可以根据同一个会话中的不同事务来清空临时表。

  另外还要说明的一点就是,ORACLE的会话型临时中的内容对于各个用户来说,内容都是独立的。具体的说,就是各个用户在会话的过程中,都可以往一张临时表中存储数据但是用户查询临时表中的数据的时候,只能够查询到自己所创建的内容,而不能看到其他用户所增加的记录。这对于临时表的安全性来说,是非常有保障的。
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

三种主流数据库中临时表的使用  

2011-03-31 22:04:35|  分类: 数据库知识 |  标签:|字号大小 订阅

MS SQLSERVER
SQL Server 支持临时表。临时表就是那些名称以井号 (#) 开头的表。如果当用户断开连接时没有除去临时表,SQL Server 将自动除去临时表。临时表不存储在当前数据库内,而是存储在系统数据库 tempdb 内。
临时表有两种类型: 
本地临时表:本地临时表的名称以单个数字符号 (#) 打头;它们仅对当前的用户连接是可见的;当用户从 Microsoft SQL Server 2000 实例断开连接时被删除。
全局临时表:全局临时表的名称以数学符号 (##) 打头,创建后对任何用户都是可见的。如果在创建全局临时表的连接断开前没有显式地除去这些表,那么只要所有其它任务停止引用它们,这些表即被除去。当创建全局临时表的连接断开后,新的任务不能再引用它们。当前的语句一执行完,任务与表之间的关联即被除去;因此通常情况下,只要创建全局临时表的连接断开,全局临时表即被除去。
例如,如果创建名为 employees 的表,则任何人只要在数据库中有使用该表的安全权限就可以使用该表,除非它已删除。如果创建名为 #employees 的本地临时表,只有您能对该表执行操作且在断开连接时该表删除。如果创建名为 ##employees 的全局临时表,数据表中的任何用户均可对该表执行操作。如果该表在您创建后没有其他用户使用,则当您断开连接时该表删除。如果该表在您创建后有其他用户使用,则 SQL Server在所有用户断开连接后删除该表。
现在,临时表的许多传统用途可由具有 table 数据类型的变量替换。

ORACLE
Oracle支持临时表。临时表用来保存事务或会话期间的中间结果。在临时表中保存的数据只有对当前会话是可见的,任何会话都不能看到其他会话的数据,即使在当前会话COMMIT数据以后也是不可见的。多用户并行不是问题,一个会话从来不阻塞另一个会话使用临时表。即使锁定临时表,一个会话也不会阻塞其他会话使用临时表。临时表比正常表产生的REDO少得多,然而,由于临时表必须产生包含数据的UNDO信息,所以会产生一定数量的REDO日志。
临时表将从用户临时表空间的的目前日志中分配空间,或者如果从有定义权的程序中访问,将使用程序所有者的临时表空间。全局临时表实际上只是表本身的模板。创建临时表的行为不包括存储空间的分配,也不包括INITIAL的分配。因此,在运行时当一个会话首先将数据放到临时表中时,这时将创建这个会话的临时段。由于每个会话获取自己的临时段,每个用户可能在不同的表空间中为临时表分配空间。USER1default临时表空间为TEMP1,他的临时表将从TEMP1中分配空间,USER2default临时表空间为TEMP2,他的临时表将从TEMP2中分配空间。
临时表在每个数据库中只需创建一次,不必在每个存储过程中创建。临时表总是存在的,除非手动的删除他。临时表作为对象存在数据字典中,并且总是保持为空,直到有会话在其中放入数据。Oracle允许创建基于临时表的视图和存储过程。
临时表可以是以会话为基础的,也可以是以事务为基础的。ON COMMIT PRESERVE ROWS子句使临时表成为基于会话的模式。行将留在此表中,直到会话断开或通过DELETETRUNCATE从物理上删除这些行。ON COMMIT DELETE ROWS子句使临时表成为基于事务的模式。当会话提交后,行消失。这个临时表的自动清除过程不会有额外的开销。
oracle中,应用程序需要的临时表应该在程序安装时创建,而不是在程序运行时创建。(这是与ms sqlserversybase的使用的不同)
在任何数据库中,临时表的一个缺点是:事实上优化器在临时表中没有真正的统计功能。然而,在oracle中,一系列较好的统计猜测可以通过DBMS_STATS包在临时表中设置。


 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是几道 Oracle 存储过程的习题: 1. 编写一个存储过程,实现对指定表的批量插入操作。该存储过程应接受表名和插入数据集合作为参数。 2. 编写一个存储过程,用于计算两个数的和并返回结果。该存储过程应接受两个数作为参数,并返回它们的和。 3. 编写一个存储过程,用于从指定表中删除符合条件的记录。该存储过程应接受表名和删除条件作为参数。 4. 编写一个存储过程,用于将指定表的记录导出到指定的 CSV 文件中。该存储过程应接受表名和文件路径作为参数。 5. 编写一个存储过程,用于更新指定表中的记录。该存储过程应接受表名、更新字段和更新条件作为参数。 6. 编写一个存储过程,用于查询指定表中的记录。该存储过程应接受表名、查询字段和查询条件作为参数。 7. 编写一个存储过程,用于将指定的字符串按照指定的分隔符进行拆分,并返回拆分后的结果集。该存储过程应接受待拆分字符串和分隔符作为参数。 8. 编写一个存储过程,用于查询指定表中的记录总数。该存储过程应接受表名作为参数,并返回符合条件的记录总数。 9. 编写一个存储过程,用于查询指定表中的前 N 条记录。该存储过程应接受表名和记录数 N 作为参数,并返回符合条件的前 N 条记录。 10. 编写一个存储过程,用于查询指定表中的记录,并按照指定的字段进行排序。该存储过程应接受表名、排序字段和排序方式作为参数,并返回符合条件的记录按照指定字段排序后的结果集。 这些习题涵盖了 Oracle 存储过程的一些常见应用场景,希望对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值