SQL Loop Executing after intended - plsql

I am attempting to run this code, I know the elements of the Loop are working, and I know the update statement does update. When I run the script with some print statements, it prints the UPDATE information first, then the LOOP information, therefore the update has no information.
PROCEDURE UpdateGridStats(p_grid_name VARCHAR2, p_region_name VARCHAR2) IS
CURSOR c1 IS
SELECT grd.globalid grid_globalid, wp.globalid workpoint_globalid, wp.feature_class_name workpoint_fcname,
tt.work_order_task_type task_type_name
FROM workorderpoint_evw wp, rpt_grid grd, workordertasktype_evw tt
WHERE grd.grid_name = p_grid_name
AND wp.work_order_task_type_globalid = tt.globalid
AND grd.rpt_region = p_region_name
AND sde.st_relation_operators.st_within_f(wp.shape, grd.shape) = 1;
v_count NUMBER := 0;
v_pole_insp_count NUMBER := 0;
v_pole_damage_count NUMBER := 0;
v_cond_damage_count NUMBER := 0;
BEGIN
FOR work_rec IN c1
LOOP
BEGIN
v_count := v_count + 1;
IF work_rec.task_type_name = 'Pole Inspection'
THEN
v_pole_insp_count := v_pole_insp_count + 1;
END IF;
IF work_rec.task_type_name = 'Pole Damage'
THEN
v_pole_damage_count := v_pole_damage_count + 1;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('==> No data found for work record ');
END;
END LOOP;
dbms_output.put_line(v_pole_damage_count || ',' ||v_pole_insp_count);
UPDATE rpt_grid grd SET da_pole_count = v_pole_damage_count, ins_structure_count = v_pole_insp_count
WHERE grd.grid_name = p_grid_name
AND grd.rpt_region = p_region_name;
END UpdateGridStats;

Maybe you just forgot to commit your changes?
Here is a simpler version of your stored procedure.
CREATE OR REPLACE PROCEDURE update_grid_stats(p_grid_name VARCHAR2, p_region_name VARCHAR2)
IS
v_ins_structure_count rpt_grid.ins_structure_count%TYPE;
v_da_pole_count rpt_grid.da_pole_count%TYPE;
BEGIN
UPDATE rpt_grid grd
SET (ins_structure_count, da_pole_count) =
(
SELECT
COUNT(CASE WHEN tt.work_order_task_type = 'Pole Inspection' THEN 1 END),
COUNT(CASE WHEN tt.work_order_task_type = 'Pole Damage' THEN 1 END)
FROM workorderpoint_evw wp
JOIN workordertasktype_evw tt ON wp.work_order_task_type_globalid = tt.globalid
WHERE sde.st_relation_operators.st_within_f(wp.shape, grd.shape) = 1
)
WHERE grd.grid_name = p_grid_name
AND grd.rpt_region = p_region_name
RETURNING ins_structure_count, da_pole_count
INTO v_ins_structure_count, v_da_pole_count;
dbms_output.put_line(
SQL%ROWCOUNT || ' rows got updated. Values: ' ||
'ins_structure_count = ' || v_ins_structure_count ||
', da_pole_count = ' || v_da_pole_count
);
COMMIT;
END update_grid_stats;
The variables and the RETURNING clause are merely needed for the output. If you don't need the output, you can remove them.

if I understand correcatally, the proc works OK, but the print statemnts are not. I beleve the print operations are on a different thread. To overcome this issue, try to replace your pront statment with raiserror function :
declare #mag varchar(max) = 'Hllo world'
raiserror ( #ERR_MSG ,0, 1) with nowait;

Related

How does one find out how a DBF file or any file is formatted?

I am attempting to pick apart a DBF file using the code in THIS AskTom post however I have no clue where I would even go to figure out how the files I'm wanting to pick apart are formatted? How was the original AskTom answer even produced? How do I figure out the dbf Header. How do I know where within the dbf file the data is stored or even how to pull out that data?
My goal is to work with the code provided and come up with a solution as others have done but I'm stuck at the very first part.
While researching this I found that there are many systems that use DBF files. ACCESS and MS Excel have the ability to import DBF files but none of those features worked when I attempted to import the DBF files from my Oracle Express installation. When in ACCESS there are options to choose from several different dbf file formats including dBASE III, dBASE IV, dBASE 5, and dBASE 7. I have no idea if Oracle is even any of these formats and wish I knew how to find out this information. Fox Pro appears to be the main user of dbf files regarding the formats I listed.
The code in that AskTom link is very long and isn't necessarily relevant to this question but just so you know where I'm coming from I've included it anyway. I can run the code but it just doesn't work. I'd love to fix it but I would need knowledge of Oracles DBF files or perhaps there is something else I am missing?
How to Read a DBase File in Java or Oracle PL/SQL
What is the best opensource dbf driver for java?
create or replace package dbase_fox as
-- procedure to a load a table with records
-- from a DBASE file.
--
-- Uses a BFILE to read binary data and dbms_sql
-- to dynamically insert into any table you
-- have insert on.
--
-- p_filename is the name of a file in that directory
-- will be the name of the DBASE file
-- p_colnames is an optional list of comma separated
-- column names. If not supplied, this pkg
-- assumes the column names in the DBASE file
-- are the same as the column names in the
-- table
-- p_rownum boolean that activates an autonum
-- functionality such that a sequential
-- numbered virtual column is created
/* EXAMPLE USAGE
| BEGIN
|
| dbase_fox.showtable(p_filename => 'CONTROL'
| , p_colnames => null
| , p_rownum => false);
|
| END;
*/
procedure loadtable(p_filename in varchar2
, p_colnames in varchar2 default null
, p_rownum in boolean default false);
-- procedure to print (and not insert) what we find in
-- the DBASE files (not the data, just the info
-- from the dbase headers....)
--
-- p_filename is the name of a file in that directory
-- will be the name of the DBASE file
-- p_colnames is an optional list of comma separated
-- column names. If not supplied, this pkg
-- assumes the column names in the DBASE file
-- are the same as the column names in the
-- table
-- p_rownum boolean that activates an autonum
-- functionality such that a sequential
-- numbered virtual column is created
procedure showtable(p_filename in varchar2
, p_colnames in varchar2 default null
, p_rownum in boolean default false);
end;
/
/* Package BODY */
create or replace package body dbase_fox as
PREFIX constant varchar2(32) default 'stage_';
CR constant varchar(2) default chr(13)||chr(10);
MEMODTYPE constant varchar2(32) default 'varchar2(4000)';
ROWNUMNAME constant varchar2(32) default '"ROWNUM"';
FRAMESIZE constant integer default 1000;
addrownum boolean := false;
colnames varchar2(255) := '';
filename varchar2(32) := '';
dbfbfile bfile := null;
fptbfile bfile := null;
DBF_HEADER_SIZE constant number default 32;
type dbf_header_type is record (
version varchar2(25) -- dBASE version number
,year int -- 1 byte int year, add to 1900
,month int -- 1 byte month
,day int -- 1 byte day
,no_records int -- number of records in file, 4 byte int
,hdr_len int -- length of header, 2 byte int
,rec_len int -- number of bytes in record, 2 byte int
,no_fields int -- number of fields
);
dbf_header dbf_header_type := null;
subtype dbf_header_data is raw(32);
DBF_FIELD_DESCRIPTOR_SIZE constant number default 32;
type dbf_field_descriptor_type is record (
name varchar2(11)
,type char(1)
,length int -- 1 byte length
,decimals int -- 1 byte scale
);
type dbf_field_descriptor_array is table of dbf_field_descriptor_type index by binary_integer;
subtype dbf_field_descriptor_data is raw(32);
dbf_field_descriptor dbf_field_descriptor_array;
type rowarray_type is table of dbms_sql.varchar2_table index by binary_integer;
rowarray rowarray_type;
subtype raw_type is raw(4000);
type rawarray_type is table of raw_type index by binary_integer;
rawarray rawarray_type;
loadcursor binary_integer;
mblocksize number := 0;
procedure get_header is
l_data dbf_header_data;
begin
l_data := dbms_lob.substr(dbfbfile, DBF_HEADER_SIZE, 1);
dbf_header.version := utl_raw.cast_to_binary_integer(utl_raw.substr(l_data, 1, 1));
dbf_header.year := 1900 + utl_raw.cast_to_binary_integer(utl_raw.substr( l_data, 2, 1));
dbf_header.month := utl_raw.cast_to_binary_integer(utl_raw.substr(l_data, 3, 1));
dbf_header.day := utl_raw.cast_to_binary_integer(utl_raw.substr(l_data, 4, 1));
dbf_header.no_records := utl_raw.cast_to_binary_integer(utl_raw.substr(l_data, 5, 4),2);
dbf_header.hdr_len := utl_raw.cast_to_binary_integer(utl_raw.substr(l_data, 9, 2),2);
dbf_header.rec_len := utl_raw.cast_to_binary_integer(utl_raw.substr(l_data, 11, 2),2);
dbf_header.no_fields := trunc((dbf_header.hdr_len - DBF_HEADER_SIZE) / DBF_FIELD_DESCRIPTOR_SIZE);
end;
procedure get_header_fields is
l_data dbf_field_descriptor_data;
begin
for i in 1 .. dbf_header.no_fields loop
l_data := dbms_lob.substr(dbfbfile, DBF_FIELD_DESCRIPTOR_SIZE, 1+DBF_HEADER_SIZE+(i-1)*DBF_FIELD_DESCRIPTOR_SIZE); -- starting past the header
dbf_field_descriptor(i).name := rtrim(utl_raw.cast_to_varchar2(utl_raw.substr(l_data,1,11)),chr(0));
dbf_field_descriptor(i).type := utl_raw.cast_to_varchar2(utl_raw.substr(l_data, 12, 1));
dbf_field_descriptor(i).length := utl_raw.cast_to_binary_integer(utl_raw.substr(l_data, 17, 1));
dbf_field_descriptor(i).decimals := utl_raw.cast_to_binary_integer(utl_raw.substr(l_data,18,1));
end loop;
end;
procedure show_field_header_columns is
begin
dbms_output.put_line(CR||'Num'
||chr(9)||'Name '
||chr(9)||'Type'
||chr(9)||'Length'
||chr(9)||'Decimals');
dbms_output.put_line('==='
||chr(9)||'==== '
||chr(9)||'===='
||chr(9)||'======'
||chr(9)||'========');
end;
procedure show_header(p_file_length in integer) is
begin
dbms_output.put_line(chr(9)||dbf_header.version
||chr(9)||dbf_header.year
||chr(9)||dbf_header.month
||chr(9)||dbf_header.day
||chr(9)||dbf_header.no_records
||chr(9)||dbf_header.hdr_len
||chr(9)||dbf_header.rec_len
||chr(9)||dbf_header.no_fields
||chr(9)||p_file_length);
end;
procedure show_fields is
begin
for i in dbf_field_descriptor.first .. dbf_field_descriptor.last loop
dbms_output.put_line(i
||chr(9)||rpad(dbf_field_descriptor(i).name,11,' ')
||chr(9)||dbf_field_descriptor(i).type
||chr(9)||dbf_field_descriptor(i).length
||chr(9)||dbf_field_descriptor(i).decimals);
end loop;
end;
function build_insert return varchar2 is
l_statement long;
begin
l_statement := 'insert into ' || PREFIX || filename || ' (';
if colnames is not null then
l_statement := l_statement || colnames;
else
for i in dbf_field_descriptor.first .. dbf_field_descriptor.last loop
if i <> 1 then
l_statement := l_statement || ',';
end if;
l_statement := l_statement || '"'|| dbf_field_descriptor(i).name || '"';
end loop;
if addrownum then
l_statement := l_statement || ',' || ROWNUMNAME;
end if;
end if;
l_statement := l_statement || ') values (';
for i in dbf_field_descriptor.first .. dbf_field_descriptor.last loop
if i <> 1 then
l_statement := l_statement || ',';
end if;
if dbf_field_descriptor(i).type = 'D' then
l_statement := l_statement || 'to_date(:bv' || i || ',''yyyymmdd'' )';
else
l_statement := l_statement || ':bv' || i;
end if;
end loop;
if addrownum then
l_statement := l_statement || ',:bv' || (dbf_field_descriptor.last + 1);
end if;
l_statement := l_statement || ')';
return l_statement;
end;
function build_create return varchar2 is
l_statement long;
begin
l_statement := 'create table ' || PREFIX || filename || ' (';
for i in dbf_field_descriptor.first .. dbf_field_descriptor.last loop
l_statement := l_statement || CR;
if i <> dbf_field_descriptor.first then
l_statement := l_statement ||',';
else
l_statement := l_statement ||' ';
end if;
l_statement := l_statement || '"'|| dbf_field_descriptor(i).name || '"'||chr(9);
if dbf_field_descriptor(i).type = 'D' then
l_statement := l_statement || 'date';
elsif dbf_field_descriptor(i).type = 'F' then
l_statement := l_statement || 'float';
elsif dbf_field_descriptor(i).type = 'N' then
if dbf_field_descriptor(i).decimals > 0 then
l_statement := l_statement || 'number('||dbf_field_descriptor(i).length||','|| dbf_field_descriptor(i).decimals || ')';
else
l_statement := l_statement || 'number('||dbf_field_descriptor(i).length||')';
end if;
elsif dbf_field_descriptor(i).type = 'M' then
l_statement := l_statement || MEMODTYPE;
else
l_statement := l_statement || 'varchar2(' || dbf_field_descriptor(i).length || ')';
end if;
end loop;
if addrownum then
l_statement := l_statement || CR || ',' || ROWNUMNAME || chr(9) || 'number';
end if;
l_statement := l_statement ||CR||');'||CR||'/';
return l_statement;
end;
procedure show_header_columns is
begin
dbms_output.put_line(CR||'DBASE File'
||chr(9)||'Version'
||chr(9)||'Year'
||chr(9)||'Month'
||chr(9)||'Day'
||chr(9)||'#Recs'
||chr(9)||'HdrLen'
||chr(9)||'RecLen'
||chr(9)||'#Fields'
||chr(9)||'Size');
dbms_output.put_line('=========='
||chr(9)||'======='
||chr(9)||'===='
||chr(9)||'====='
||chr(9)||'==='
||chr(9)||'====='
||chr(9)||'======'
||chr(9)||'======'
||chr(9)||'======='
||chr(9)||'====');
end;
procedure loadtablerecord(i in number) is
l_n number;
l_fblock number;
l_data raw_type;
begin
l_data := dbms_lob.substr(dbfbfile,dbf_header.rec_len,2+DBF_HEADER_SIZE+dbf_header.no_fields*DBF_FIELD_DESCRIPTOR_SIZE+(i-1)*dbf_header.rec_len); -- starting past the header and field descriptors
rawarray(0) := utl_raw.substr(l_data, 1, 1);
l_n := 2;
for j in 1 .. dbf_header.no_fields loop
rawarray(j) := utl_raw.substr(l_data,l_n,dbf_field_descriptor(j).length);
if dbf_field_descriptor(j).type = 'F' and rawarray(j) = '.' then
rawarray(j) := null;
elsif dbf_field_descriptor(j).type = 'M' then
if dbms_lob.isopen(fptbfile) != 0 then
l_fblock := nvl(utl_raw.cast_to_binary_integer(dbms_lob.substr(fptbfile, 4, to_number(trim(utl_raw.cast_to_varchar2(rawarray(j))))*mblocksize+5)),0);
rawarray(j) := dbms_lob.substr(fptbfile, l_fblock, to_number(trim(utl_raw.cast_to_varchar2(rawarray(j))))*mblocksize+9);
else
dbms_output.put_line(filename || '.fpt not found');
end if;
end if;
l_n := l_n + dbf_field_descriptor(j).length;
end loop;
end;
procedure loadtablearray(p_cntarr in int) is
l_bulkcnt number;
begin
for j in 1 .. dbf_header.no_fields loop
dbms_sql.bind_array(loadcursor, ':bv'||j, rowarray(j),1,p_cntarr);
end loop;
if addrownum then
dbms_sql.bind_array(loadcursor, ':bv'||(dbf_header.no_fields+1), rowarray(dbf_header.no_fields+1),1,p_cntarr);
end if;
begin
l_bulkcnt := dbms_sql.execute(loadcursor);
--dbms_output.put_line('Bulk insert count ' || l_bulkcnt);
exception
when others then
dbms_output.put_line('Bulk insert failed ' || sqlerrm);
dbms_output.put_line(build_insert);
end;
end;
procedure loadtablebulk is
l_cntrow int default 0;
l_cntarr int default 0;
begin
loadcursor := dbms_sql.open_cursor;
dbms_sql.parse(loadcursor, build_insert, dbms_sql.native);
for i in 1 .. dbf_header.no_records loop
loadtablerecord(i);
if utl_raw.cast_to_varchar2(rawarray(0)) <> '*' then
l_cntarr := l_cntarr + 1;
for j in 1 .. dbf_header.no_fields loop
rowarray(j)(l_cntarr) := trim(utl_raw.cast_to_varchar2(rawarray(j)));
end loop;
if addrownum then
l_cntrow := l_cntrow + 1;
rowarray((dbf_header.no_fields+1))(l_cntarr) := l_cntrow;
end if;
if l_cntarr >= FRAMESIZE then
loadtablearray(l_cntarr);
l_cntarr := 0;
end if;
end if;
end loop;
if l_cntarr > 0 then
loadtablearray(l_cntarr);
end if;
dbms_sql.close_cursor(loadcursor);
exception
when others then
if dbms_sql.is_open(loadcursor) then
dbms_sql.close_cursor(loadcursor);
end if;
dbms_output.put_line('loadtable failed for ' || filename);
dbms_output.put_line('insert ' || build_insert);
end;
procedure open_dbf is
begin
dbfbfile := bfilename('FILE_GET_DIR', filename || '.dbf');
dbms_lob.fileopen(dbfbfile);
end;
procedure open_fpt is
begin
fptbfile := bfilename('FILE_GET_DIR', filename || '.fpt');
if dbms_lob.fileexists(fptbfile) != 0 then
dbms_lob.fileopen(fptbfile);
end if;
end;
procedure close_dbf is
begin
if dbms_lob.isopen(dbfbfile) > 0 then
dbms_lob.fileclose(dbfbfile);
end if;
end;
procedure close_fpt is
begin
if dbms_lob.isopen(fptbfile) > 0 then
dbms_lob.fileclose(fptbfile);
end if;
end;
procedure initialize is
l_empty_dbf_field_descriptor dbf_field_descriptor_array;
l_empty_rowarray rowarray_type;
l_empty_rawarray rawarray_type;
begin
dbfbfile := null;
fptbfile := null;
dbf_field_descriptor := l_empty_dbf_field_descriptor;
dbf_header := null;
rowarray := l_empty_rowarray;
rawarray := l_empty_rawarray;
loadcursor := 0;
mblocksize := 0;
end;
procedure showtable(p_filename in varchar2, p_colnames in varchar2 default null, p_rownum in boolean default false) is
errorAtLine NUMBER := 0;
begin
filename := p_filename;
addrownum := p_rownum;
colnames := p_colnames;
initialize;
errorAtLine := 1;
open_dbf;
errorAtLine := 2;
get_header;
errorAtLine := 3;
get_header_fields;
errorAtLine := 4;
show_header_columns;
errorAtLine := 5;
dbms_output.put(filename || '.dbf');
errorAtLine := 6;
show_header(dbms_lob.getlength(dbfbfile));
errorAtLine := 7;
show_field_header_columns;
errorAtLine := 8;
show_fields;
errorAtLine := 9;
dbms_output.put_line(CR||'Insert statement:');
dbms_output.put_line(build_insert);
dbms_output.put_line(CR||'Create statement:');
dbms_output.put_line(build_create);
close_dbf;
exception
when others then
close_dbf;
dbms_output.put_line('Error At: ' || errorAtLine);
raise;
end;
procedure loadtable(p_filename in varchar2, p_colnames in varchar2 default null, p_rownum in boolean default false) is
begin
filename := p_filename;
addrownum := p_rownum;
colnames := p_colnames;
initialize;
open_dbf;
open_fpt;
if dbms_lob.isopen(fptbfile) > 0 then
mblocksize := utl_raw.cast_to_binary_integer(dbms_lob.substr(fptbfile, 2, 7));
else
mblocksize := 0;
end if;
get_header;
get_header_fields;
loadtablebulk;
close_dbf;
close_fpt;
exception
when others then
close_dbf;
close_fpt;
raise;
end;
end;
I had a similar problem and this is how I did it.
TL;DR: You'll need to use Apache Tika to parse DBase files. It converts the content into a XHTML table and returns it as a java.lang.String, which you can parse via a DOM or a SAX parser to get the data in the format you need. Here are some examples: https://tika.apache.org/1.20/examples.html
To start, add the following Maven dependency to your POM:
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-parsers</artifactId>
<version>1.21</version>
</dependency>
Then initialize the parser:
Parser parser = new DBFParser(); //Alternatively, you can use AutoDetectParser
ContentHandler handler = new BodyContentHandler(new ToXMLContentHandler()); //This is tells the parser to produce an XHTML as an output.
parser.parse(dbaseInputStream, handler, new Metadata(), new ParseContext()); // Here, dbaseInputStream is a FileInputStream object for the DBase file.
String dbaseAsXhtml = handler.toString(); //This will have the content in XHTML format
Now, to convert the data into a more convenient format (in this case CSV), I did the following:
First, convert the whole String into a DOM object:
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document xhtmlDoc= builder.parse(new InputSource(new StringReader(xmlString.trim().replaceAll("\t", "")))); //I'm trimming out the tabs and whitespaces here, so that I don't have to dealt with them later
Now, to get the headers:
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList tableHeader = (NodeList)xPath.evaluate("//table/thead/th", xhtmlDoc, XPathConstants.NODESET);
String [] headers = new String[tableHeader.getLength()];
for(int i = 0; i < tableHeader.getLength(); i++) {
headers[i] = tableHeader.item(i).getTextContent();
}
Then the records:
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList tableRecords = (NodeList)xPath.evaluate("//table/tbody/tr", xhtmlDoc, XPathConstants.NODESET);
List<String[]> records = new ArrayList<String[]>(tableRecords.getLength());
for(int i = 0; i < tableRecords.getLength(); i++) {
NodeList recordNodes = tableRecords.item(i).getChildNodes();
String[] record = new String[recordNodes.getLength()];
for(int j = 0; j < recordNodes.getLength(); j++)
record[j] = recordNodes.item(j).getTextContent();
records.add(record);
}
Finally, we put them together to form a CSV:
StringBuilder dbaseCsvStringBuilder = new StringBuilder(String.join(",", headers) + "\n");
for(String[] record : records)
dbaseCsvStringBuilder.append(String.join(",", record) + "\n");
String csvString = dbaseCsvStringBuilder.toString();
Here's the complete source code: https://github.com/Debojit/DbaseTranslater/blob/master/src/main/java/nom/side/poc/file/dbf/DbaseReader.java

How to fetch one - one row from table

I have a table called stud_ans_sheet.
I want to run a loop
which would every time fetch next values from table.
It's a PL/SQL program and I am doing it with a cursor.
This is my program,
but it has a lot of errors:
set serveroutput on;
declare
cursor c_stud is select stud_no,ans from stud_ans_sheet;
v_stud c_stud%rowtype;
v_no stud_ans_sheet.stud_no%type;
answer varchar(10);
i number(3);
v_corr stud_ans_sheet.corr_ans%type;
v_wrong stud_ans_sheet.wrong_ans%type;
v_unattempt stud_ans_sheet.unattempt_ans%type;
score number(5,2);
v_ans varchar(10);
str1 varchar(40);
str2 varchar(40);
nval stud_ans_sheet.stud_no%type;
total number(5,2);
begin
answer:='AACCABAABD';
open c_stud;
loop
fetch c_stud into v_stud;
exit when c_stud%notfound;
for i in 1..10
loop
nval:= select seq.nextval from stud_ans_sheet.stud_no;
select stud_no,ans into v_no,v_ans from stud_ans_sheet where stud_no=nval;
str2:=substr(v_ans,i,1);
str1:=substr(answer,i,1);
if(str2=str1) then
update stud_ans_sheet
set corr_ans=v_corr+1;
elsif(str2='E') then
update stud_ans_sheet
set unattempt_ans=v_unattempt+1;
else
update stud_ans_sheet
set wrong_ans=v_wrong+1;
end if;
end loop;
update stud_ans_sheet
set score=corr_ans-wrong_ans*0.25+unattempt_ans;
end loop;
close c_stud;
end;
/
This line doesn't really make sense:
nval:= select seq.nextval from stud_ans_sheet.stud_no;
There is no variable := select ... construction in PL/SQL, and even if there was, stud_ans_sheet.stud_no isn't a table so you can't select from it, and if you could it's unclear what you want the sequence for anyway.
If you just want to copy the record attribute v_stud.stud_no into the local variable nval then you can just use:
nval := v_stud.stud_no;
but then the question is why copy it at all, when you can just use v_stud.stud_no directly?
It is generally best to avoid the verbose declare-open-fetch construction for cursors when all you need to do is loop through them. Instead, you can just use:
for r in (
select stud_no, ans from stud_ans_sheet
)
loop
I can't see why you are re-querying stud_ans_sheet in the loop just to get back the same row you already have. If it's something to do with your update logic, I couldn't tell what that was supposed to do.
The update statements in your code will update every row in the table every time, because they don't have any where clause.
In PL/SQL, if conditions are terminated by then instead of being enclosed in brackets as in some other languages, so for example,
if (str2 = str1) then
can be decluttered into:
if str2 = str1 then
The construction for i in 1..10 implicitly declares i with its scope as the loop, so the other i you declared at the top is a different variable and not used.
You are allowed to use spaces for readability, so
update stud_ans_sheet
set score=corr_ans-wrong_ans*0.25+unattempt_ans
where ...
can be written more clearly as
update stud_ans_sheet
set score = corr_ans - wrong_ans * 0.25 + unattempt_ans
where ...;
Probably you should focus on one error at a time rather than dumping the whole thing here for review.
I have changed some of your code, try this:
SET SERVEROUTPUT ON;
DECLARE
ANSWER VARCHAR (10);
V_CORR STUD_ANS_SHEET.CORR_ANS%TYPE;
V_WRONG STUD_ANS_SHEET.WRONG_ANS%TYPE;
V_UNATTEMPT STUD_ANS_SHEET.UNATTEMPT_ANS%TYPE;
STR1 VARCHAR (40);
STR2 VARCHAR (40);
BEGIN
ANSWER := 'AACCABAABD';
FOR R_STUD IN (SELECT STUD_NO, ANS
FROM STUD_ANS_SHEET)
LOOP
V_CORR := 0;--It's better to have only one update
V_WRONG := 0;
V_UNATTEMPT := 0;
FOR I IN 1 .. 10
LOOP
STR2 := SUBSTR (R_STUD.ANS, I, 1);
STR1 := SUBSTR (ANSWER, I, 1);
IF (STR2 = STR1)
THEN
V_CORR := V_CORR + 1;
ELSIF (STR2 = 'E')
THEN
V_UNATTEMPT := V_UNATTEMPT + 1;
ELSE
V_WRONG := V_WRONG + 1;
END IF;
END LOOP;
UPDATE STUD_ANS_SHEET
SET SCORE = V_CORR- V_WRONG* 0.25 + V_UNATTEMPT,
CORR_ANS = V_CORR,
WRONG_ANS = V_WRONG,
UNATTEMPT_ANS = V_UNATTEMPT
WHERE R_STUD.STUD_NO = STUD_NO;
END LOOP;
END;
/
SET SERVEROUTPUT ON;
DECLARE
aswer varchar (10);
v_corr number(3);
v_wrong number (3);
v_unattempt number (3);
str1 VARCHAR (10);
str2 VARCHAR (10);
BEGIN
answer:= 'AACCABAABD';
FOR v_stud in c_stud
LOOP
v_corr:= 0;
v_wrong:= 0;
v_unattempt := 0;
FOR I IN 1 .. 10
LOOP
str2 := SUBSTR (v_stud.ans, i, 1);
str1 := SUBSTR (answer, i, 1);
IF (str2 = str1)
THEN
v_corr := v_corr + 1;
ELSIF (str2 = 'E')
THEN
v_unattempt := v_unattempt + 1;
else
v_wrong:= v_wrong + 1;
END IF;
END LOOP;
UPDATE stud_ans_sheet
SET
corr_ans= v_corr,
wrong_ans = v_wrong,
unattempt_ans=v_unattempt , score = v_corr- v_wrong* 0.25,
WHERE stud_no= v_stud.stud_no;
END LOOP;
END;
/

create a procedure with cursor as parameter

I wrote this code and it works ok:
declare
cursor c_emp is
select last_name, first_name from employees;
type c_list is table of employees.last_name%type index by binary_integer;
type c_list2 is table of employees.first_name%type index by binary_integer;
last_list c_list;
first_list c_list2;
counter integer := 0;
begin
for i in c_emp loop
counter := counter + 1;
last_list(counter) := i.last_name;
first_list(counter) := i.first_name;
dbms_output.put_line('Employee(' || counter || '): ' || last_list(counter) || ' ' || first_list(counter));
end loop;
end;
/
This time I am trying to make procedure with parameters that I can insert the table name and column into the cursor. And I have tried with this :
create or replace procedure show_data(tab_name in varchar2, data_list in varchar2)
is
str varchar2(100);
str2 varchar2(100);
column_name varchar2(100);
begin
str := 'select ' || data_list || ' from ' || tab_name;
for vRec in str loop
dbms_output.put_line(str);
end loop;
end;
/
It gave a error which the str is not a cursor. I am not sure that if cursor can be done in this way, but from the error it seems it can't.
Which part of my code is wrong, or because I didn't declare my cursor? But if i declare my cursor, I can't get the parameter by using dynamic sql way.
The below should produce the same result as your original PL/SQL block. Note that the table_name can be dynamic and so can the data_list but you need to know the column names in the data_list to be able to fetch from the cursor and then print them.
create or replace procedure show_data(tab_name in varchar2
, data_list in varchar2)
is
str varchar2(100);
str2 varchar2(100);
column_name varchar2(100);
TYPE cursor_ref IS REF CURSOR;
vRec_cursor cursor_ref;
counter integer = 0;
last_name employee.last_name%TYPE;
first_name employee.first_name%TYPE;
begin
str := 'select ' || data_list || ' from ' || tab_name;
open vRec_cursor for str;
loop
FETCH vRec_cursor INTO last_name, first_name;
EXIT WHEN vRec_cursor%NOTFOUND;
dbms_output.put_line('Employee(' || counter || '): ' || last_name || ' ' || first_name;
counter = counter + 1;
end loop;
end;
/
NOTE: Haven't run the above code yet

Inserting data into Global temporary table by executing Stored Procedure in SQLPLUS

I creatd a stored procedure. And a global temporary table inside it.
Now i am inserting data into this table by fatching cursor into local variables.
create or replace PROCEDURE "DEMO"
(
PARM_YEAR IN NUMBER,
PARM_PERIOD IN NUMBER,
PARM_PERIOD_TYPE IN CHAR,
PARM_PERIOD_ROLL IN CHAR,
PARM_TYPE IN VARCHAR2,
P_CURSOR IN OUT types.cursorType
)
IS
LOC_EXISTS NUMBER;
LOC_TYPE_PERIOD CHAR(2);
LOC_CURSOR_YEAR INTEGER;
LOC_CURSOR_PERIOD INTEGER;
LOC_CURSOR_TYPE_PERIOD CHAR(2 BYTE);
LOC_CURSOR_DEV_COPCL NUMBER(10,1);
LOC_CURSOR_DIST_GRP NUMBER(3,0);
CURSOR DIST_CHART IS
SELECT X.YEAR , X.PERIOD, X.TYPE_PERIOD, X.COST AS DEV_COPCL
FROM
SMY_PRVDR_TYPE_PRVDR X;
BEGIN
/* Set Period type */
IF (PARM_PERIOD_TYPE = 'Q' AND PARM_PERIOD_ROLL = 'A') THEN
LOC_TYPE_PERIOD := 'Q';
ELSE IF (PARM_PERIOD_TYPE = 'Q' AND PARM_PERIOD_ROLL = 'R') THEN
LOC_TYPE_PERIOD := 'RQ';
ELSE IF (PARM_PERIOD_TYPE = 'M' AND PARM_PERIOD_ROLL = 'A') THEN
LOC_TYPE_PERIOD := 'M';
ELSE
LOC_TYPE_PERIOD := 'RM';
END IF;
END IF;
END IF;
LOC_EXISTS := 0;
SELECT 1 INTO LOC_EXISTS
FROM ALL_TABLES
WHERE TABLE_NAME LIKE '%DEMO1%';
IF LOC_EXISTS = 1 THEN
EXECUTE IMMEDIATE 'TRUNCATE TABLE DEMO1';
END IF;
OPEN DIST_CHART;
LOOP
FETCH DIST_CHART INTO LOC_CURSOR_YEAR, LOC_CURSOR_PERIOD, LOC_CURSOR_TYPE_PERIOD,
LOC_CURSOR_DEV_COPCL;
EXIT WHEN DIST_CHART%NOTFOUND;
SELECT DIST_GRP(LOC_CURSOR_DEV_COPCL) INTO LOC_CURSOR_DIST_GRP FROM DUAL;
EXECUTE IMMEDIATE 'INSERT INTO DEMO1 VALUES ('|| LOC_CURSOR_YEAR ||', '''||
LOC_CURSOR_PERIOD || ''', '''|| LOC_CURSOR_TYPE_PERIOD ||''', '|| LOC_CURSOR_DEV_COPCL
||', '|| LOC_CURSOR_DIST_GRP || ')';
END LOOP;
CLOSE DIST_CHART;
EXCEPTION
WHEN NO_DATA_FOUND THEN
LOC_EXISTS:=0;
END;
Problem is that..
When i am executing this stored procedure into sql developer data is inserted successfuly into the global temporary table.
But
When i run same execute command into SQLPLUS, procedure run successfully, but data is not inserted into the global temporary table.
Code of GTT is
CREATE GLOBAL TEMPORARY TABLE "ICUSER"."DEMO1"
( "YEAR" NUMBER(4,0),
"PERIOD" NUMBER(2,0),
"TYPE_PERIOD" CHAR(2 BYTE),
"DEV_COPCL" NUMBER(*,1),
"DIST_GRP" NUMBER(3,0)
) ON COMMIT PRESERVE ROWS ;

Get Installation Sequence of Oracle Objects

Ok, I have a complex recursion problem. I want to get a dependecy installation sequence of all of my objcts (all_objects table) in my Oracle 11g database.
First I have created a view holding all dependencies
create or replace
view REALLY_ALL_DEPENDENCIES as
select *
from ALL_DEPENDENCIES
union
select owner, index_name, 'INDEX', table_owner, table_name, table_type, null, null
from all_indexes
union
select p.owner, p.table_name, 'TABLE', f.owner, f.table_name, 'TABLE', null, null
from all_constraints p
join all_constraints f
on F.R_CONSTRAINT_NAME = P.CONSTRAINT_NAME
and F.CONSTRAINT_TYPE = 'R'
and p.constraint_type='P'
;
/
EDIT
I have tried do concate all dependencies by using this function:
create
or replace
function dependency(
i_name varchar2
,i_type varchar2
,i_owner varchar2
,i_level number := 0
,i_token clob := ' ') return clob
is
l_token clob := i_token;
l_exist number := 0;
begin
select count(*) into l_exist
from all_objects
where object_name = i_name
and object_type = i_type
and owner = i_owner;
if l_exist > 0 then
l_token := l_token || ';' || i_level || ';' ||
i_name || ':' || i_type || ':' || i_owner;
else
-- if not exist function recursion is finished
return l_token;
end if;
for tupl in (
select distinct
referenced_name
,referenced_type
,referenced_owner
from REALLY_ALL_DEPENDENCIES
where name = i_name
and type = i_type
and owner = i_owner
)
loop
-- if cyclic dependency stop and shout!
if i_token like '%' || tupl.referenced_name || ':' || tupl.referenced_type || ':' || tupl.referenced_owner || '%' then
select count(*) into l_exist
from REALLY_ALL_DEPENDENCIES
where name = tupl.referenced_name
and type = tupl.referenced_type
and owner = tupl.referenced_owner;
if l_exist > 0 then
return '!!!CYCLIC!!! (' || i_level || ';' || tupl.referenced_name || ':' || tupl.referenced_type || ':' || tupl.referenced_owner || '):' || l_token;
end if;
end if;
-- go into recursion
l_token := dependency(
tupl.referenced_name
,tupl.referenced_type
,i_owner /* I just want my own sources */
,i_level +1
,l_token);
end loop;
-- no cyclic condition and loop is finished
return l_token;
end;
/
And I can query through
select
object_name
,object_type
,owner
,to_char(dependency(object_name, object_type, owner)) as dependecy
from all_objects
where owner = 'SYSTEM'
;
Ok, maybe it is something like "cheating" but you can not do cyclic dependencies at creation time. So at least as a human beeing I am only able to create one object after another :-) And this sequence should be "reverse engineer able".
Now I am more interested in a solution than before ;-) And it is still about the tricky part ... "How can I select all soures from a schema orderd by its installation sequence (dependent objects list prior the using object)"?
It is just some kind of sorting problem, insn't it?
Usually you "cheat" by creating the objects in a particular order. For example, you might make sequences first (they have zero dependencies). Then you might do tables. After that, package specs, then package bodies, and so on.
Keep in mind that it is possible to have cyclic dependencies between packages, so there are cases where it will be impossible to satisfy all dependencies at creation anyway.
What's the business case here? Is there a real "problem" or just an exercise?
EDIT
The export tool we use exports objects in the following order:
Database Links
Sequences
Types
Tables
Views
Primary Keys
Indexes
Foreign Keys
Constraints
Triggers
Materialized Views
Materialized View Logs
Package Specs
Package Bodies
Procedures
Functions
At the end, we run the dbms_utility.compile_schema procedure to make sure everything is valid and no dependencies are missed. If you use other object types than these, I'm not sure where they'd go in this sequence.
Ok, I had some time to look at the job again and I want to share the results. Maybe anotherone comes across this thread searching for a solution. First of all I did the SQLs as SYS but I think you can do it in every schema using public synonyms.
The Procedure "exec obj_install_seq.make_install('SCOTT');" makes a clob containing a sql+ compatible sql file, assuming your sources are called "object_name.object_type.sql". Just spool it out.
Cheers
Chris
create global temporary table DEPENDENCIES on commit delete rows as
select * from ALL_DEPENDENCIES where 1=2 ;
/
create global temporary table install_seq(
idx number
,seq number
,iter number
,owner varchar2(30)
,name varchar2(30)
,type varchar2(30)
) on commit delete rows;
/
create global temporary table loop_chk(
iter number
,lvl number
,owner varchar2(30)
,name varchar2(30)
,type varchar2(30)
) on commit delete rows;
/
create or replace package obj_install_seq is
procedure make_install(i_schema varchar2 := 'SYSTEM');
end;
/
create or replace package body obj_install_seq is
subtype install_seq_t is install_seq%rowtype;
type dependency_list_t is table of DEPENDENCIES%rowtype;
procedure set_list_data(i_schema varchar2 := user)
is
l_owner varchar2(30) := i_schema;
begin
-- collect all dependencies
insert into DEPENDENCIES
select *
from (select *
from ALL_DEPENDENCIES
where owner = l_owner
and referenced_owner = l_owner
union
select owner, index_name, 'INDEX', table_owner, table_name, table_type, null, null
from all_indexes
where owner = l_owner
and table_owner = l_owner
union
select p.owner, p.table_name, 'TABLE', f.owner, f.table_name, 'TABLE', null, null
from all_constraints p
join all_constraints f
on F.R_CONSTRAINT_NAME = P.CONSTRAINT_NAME
and F.CONSTRAINT_TYPE = 'R'
and p.constraint_type='P'
and p.owner = f.owner
where p.owner = l_owner
) all_dep_tab;
-- collect all objects
insert into install_seq
select rownum, null,null, owner, object_name, object_type
from (select distinct owner, object_name, object_type, created
from all_objects
where owner = l_owner
order by created) objs;
end;
function is_referencing(
i_owner varchar2
,i_name varchar2
,i_type varchar2
,i_iter number
,i_level number := 0
) return boolean
is
l_cnt number;
begin
select count(*) into l_cnt
from loop_chk
where name = i_name
and owner = i_owner
and type = i_type
and iter = i_iter
and lvl < i_level;
insert into loop_chk values(i_iter,i_level,i_owner,i_name,i_type);
if l_cnt > 0 then
return true;
else
return false;
end if;
end;
procedure set_seq(
i_owner varchar2
,i_name varchar2
,i_type varchar2
,i_iter number
,i_level number := 0)
is
-- l_dep all_dependencies%rowtype;
l_idx number;
l_level number := i_level +1;
l_dep_list dependency_list_t;
l_cnt number;
begin
-- check for dependend source
begin
select * bulk collect into l_dep_list
from dependencies
where name = i_name
and owner = i_owner
and type = i_type;
if l_dep_list.count <= 0 then
-- recursion finished
return;
end if;
end;
for i in 1..l_dep_list.count loop
if is_referencing(
l_dep_list(i).referenced_owner
,l_dep_list(i).referenced_name
,l_dep_list(i).referenced_type
,i_iter
,i_level
) then
-- cyclic dependecy
update install_seq
set seq = 999
,iter = i_iter
where name = l_dep_list(i).referenced_name
and owner = l_dep_list(i).referenced_owner
and type = l_dep_list(i).referenced_type;
else
--chek if sequence is earlier
select count(*) into l_cnt
from install_seq
where name = l_dep_list(i).referenced_name
and owner = l_dep_list(i).referenced_owner
and type = l_dep_list(i).referenced_type
and seq > l_level *-1;
-- set sequence
if l_cnt > 0 then
update install_seq
set seq = l_level *-1
,iter = i_iter
where name = l_dep_list(i).referenced_name
and owner = l_dep_list(i).referenced_owner
and type = l_dep_list(i).referenced_type;
end if;
-- go recusrion
set_seq(
l_dep_list(i).referenced_owner
,l_dep_list(i).referenced_name
,l_dep_list(i).referenced_type
,i_iter + (i-1)
,l_level
);
end if;
end loop;
end;
function get_next_idx return number
is
l_idx number;
begin
select min(idx) into l_idx
from install_seq
where seq is null;
return l_idx;
end;
procedure make_install(i_schema varchar2 := 'SYSTEM')
is
l_obj install_seq_t;
l_idx number;
l_iter number := 0;
l_install_clob clob := chr(10);
begin
set_list_data(i_schema);
l_idx := get_next_idx;
while l_idx is not null loop
l_iter := l_iter +1;
select * into l_obj from install_seq where idx = l_idx;
update install_seq set iter = l_iter where idx = l_idx;
update install_seq set seq = 0 where idx = l_idx;
set_seq(l_obj.owner,l_obj.name,l_obj.type,l_iter);
l_idx := get_next_idx;
end loop;
for tupl in ( select * from install_seq order by seq, iter, idx ) loop
l_install_clob := l_install_clob || '#' ||
replace(tupl.name,' ' ,'') || '.' ||
replace(tupl.type,' ' ,'') || '.sql' ||
chr(10);
end loop;
l_install_clob := l_install_clob ||
'exec dbms_utility.compile_schema(''' || upper(i_schema) || ''');';
-- do with the install file what you want
DBMS_OUTPUT.PUT_LINE(dbms_lob.substr(l_install_clob,4000));
end;
end;
/

Resources