I tried the following stored procedure for copying one table records from one schema table to another schema table.
CREATE OR REPLACE PROCEDURE ARCHIVE_DATA
AS
cursor C_BRIC_EXTRACT
is
select pend_date, pend_note, record_id, suspense_cd, suspense_date from DEV_SWIMLANE2.billing_record_invoiced_code;
BEGIN
FOR C_EXTRACT_BRIC_REC IN C_BRIC_EXTRACT
LOOP
BEGIN
INSERT INTO
DEV_ARCHIVE.BRIC_ARCHV(SUSPENSE_CD,RECORD_ID,SUSPENSE_DATE,PEND_DATE,PEND_NOTE)
VALUES
(C_EXTRACT_BRIC_REC.SUSPENSE_CD, C_EXTRACT_BRIC_REC.RECORD_ID, C_EXTRACT_BRIC_REC.SUSPENSE_DATE, C_EXTRACT_BRIC_REC.PEND_DATE, C_EXTRACT_BRIC_REC.PEND_NOTE);
COMMIT;
END;
END LOOP;
END;
But I am getting the following error message:
17:20:27 [CREATE - 0 row(s), 0.000 secs] [Error Code: 1031, SQL State: 42000] ORA-01031: insufficient privileges
17:20:27 [BEGIN - 0 row(s), 0.000 secs] [Error Code: 6550, SQL State: 65000] ORA-06550: line 8, column 159:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
;
17:20:27 [COMMIT - 0 row(s), 0.293 secs] Command processed. No rows were affected
17:20:28 [END - 0 row(s), 0.000 secs] [Error Code: 900, SQL State: 42000] ORA-00900: invalid SQL statement
17:20:29 [END - 0 row(s), 0.000 secs] [Error Code: 900, SQL State: 42000] ORA-00900: invalid SQL statement
17:20:29 [END - 0 row(s), 0.000 secs] [Error Code: 900, SQL State: 42000] ORA-00900: invalid SQL statement
Please help me how to set the privileges and also please let me know whether there is any issue on my stored procedure in oracle.
You don't need a stored procedure and definitely not a cursor for this. It is much more efficient to do this with a single statement.
Edit to generate a unique value for the ARCHIVE_ID column, you should create a sequence:
CREATE SEQUENCE SEQ_ARCHIVE_ID;
and then use that in the insert statement:
INSERT INTO DEV_ARCHIVE.BRIC_ARCHV
(ARCHIVE_ID, SUSPENSE_CD, RECORD_ID, SUSPENSE_DATE, PEND_DATE, PEND_NOTE)
select seq_archive_id.nextval,
suspense_cd,
record_id,
suspense_date,
pend_date,
pend_note
from DEV_SWIMLANE2.billing_record_invoiced_code;
COMMIT;
If you do want to have it in a stored procedure, you can put the above statement in one. But you should definitely get rid of the slow row-by-row inserts using the cursor. The fact that you commit each and every record makes this even worse.
Regarding your errors:
ORA-01031: insufficient privileges
simply means that the user under which your procedure is execute either does not have the privilege to select from the source table or the user does not have the privilege to insert into the target table. You will need to make sure the necessary GRANTs have been given.
If you are logged in as the user DEV_ARCHIVE you can run:
GRANT INSERT ON BRIC_ARCHV TO DEV_SWIMLANE2;
to give the user DEV_SWIMLANE2 the privilege to insert into the target table.
or alternatively, if you are logged in as DEV_SWIMLANE2 you can run:
GRANT SELECT ON billing_record_invoiced_code TO DEV_ARCHIVE;
to give the user DEV_ARCHIVE the privilege to select from the source table. Which one you prefer is a matter of choice. I'd probably use the second version: giving the target user the privilege to read the source data.
Related
I have a simple stored procedure to calculate the sum of salaries of employees, sum of their squares and number of rows.
This is the stored procedure I have written:
I get an error in fetching the number of rows from the database and assigning it to a variable. What do I do? Using DB2 11.5
It helps to specify the exact error code when asking questions (don't write get an error, do write instead 'get error SQL0104N ...`.
Your mistake is that you have not followed the documented order for SQL statements in compound SQL blocks.
The SELECT statement can only appear after any cursor definitions, local procedures , and handlers if you have any.
So move the statement SELECT COUNT(*) INTO TOTAL_ROWS FROM EMPLOYEE; so that it appears after the DECLARE CURSOR1 ... line, the try to recompile.
My Agenda is to store the counts of the 2 tables ( being passed in the parameter ) and then do some more operations upon comparing the both.
PROBLEM -
Stored Procedure throwing Error :
CREATE OR REPLACE PROCEDURE dev.gp_count_matching_20191204(actual_tablename character varying(256), bkp_tablename character varying(256))
LANGUAGE plpgsql
AS $$
DECLARE
actual_table_name varchar(256);
backup_table_name varchar(256);
actual_count_query varchar(1024);
actual_count int;
backup_count_query varchar(1024);
backup_count int;
BEGIN
call dev.gp_test_error_handling_tablename_format(actual_tablename);
call dev.gp_test_error_handling_tablename_format(bkp_tablename);
actual_count:=(select count(*) as counts from actual_tablename);
--raise info 'Actual Table Name - %, Actual Table Count - %',actual_tablename,actual_count;
end;
$$
This throws the following Error while creating the stored procedure-
An error occurred when executing the SQL command:
CREATE OR REPLACE PROCEDURE dev.gp_count_matching_20191204(actual_tablename character varying(256), bkp_tablename character varying(256))
LANGUAGE pl...
[Amazon](500310) Invalid operation: syntax error at or near "$1";
1 statement failed.
Execution time: 0.99s
If I comment out the actual_count:=(select count(*) as counts from actual_tablename);
then the Stored Procedure gets created Successfully.
I guess it has something to do with me using the parameter ( since $1 points the first parameter ) in the query.
Since I am pretty new with Stored procedure, I unable to figure out the exact problem.
Thanks in Advance.
You need to use EXECUTE when running dynamic SQL. In your example the query is in parentheses but nothing is making it execute. To execute the query into a variable you using the INTO syntax
sql := 'SELECT …'
EXECUTE sql_var INTO result_var;
Please see the example Stored Procedures in our GitHub repo "Amazon Redshift Utils". https://github.com/awslabs/amazon-redshift-utils/tree/master/src/StoredProcedures
There are several examples that use dynamic SQL, such as https://github.com/awslabs/amazon-redshift-utils/blob/master/src/StoredProcedures/sp_split_table_by_range.sql
You can also use the below-given syntax:
SELECT INTO Count count(*) from table_name;
By doing this you are inserting the value of count(*) into variable Count. It works.
I'm writing procedure to transfer data from table in one Db named as 'Dev( or testing)' to another table in fdw db where we'll have repository table. Every month, last business day -2, we'll clean data from dev table and transfer it to repository table.
I'm super new to this technology and testing procedure and getting follwiing error
[Error] ORA-00904 (12: 15):
PL/SQL: ORA-00904: "USB"."BAS2_AGENCY_TO_RISKRATE_REPOS"."AS_OF_DATE: invalid identifier
CREATE OR REPLACE PROCEDURE USB.Basel2_riskrating
AS
BEGIN
INSERT INTO USB.BAS2_AGENCY_TO_RISKRATE_REPOS#OFSADEV --INSERTS DATA IN REPOSITORY TABLE
SELECT *
FROM USB.BAS2_AGENCY_TO_RISKRATING_TRAN M
WHERE USB.BAS2_AGENCY_TO_RISKRATE_REPOS.AS_OF_DATE != M.AS_OF_DATE ; --COMPARES DATE COLUMN TO REMOVE DUPLICACY
COMMIT;
END Basel2_riskrating;
Could you please help me in this. Also, it will be great if one could guide me with sample procedure code in wiping data from USB.BAS2_AGENCY_TO_RISKRATING_TRAN table at each month end.
As suggested in the comments, use NOT EXISTS. It's not celar whether you want to check for duplicates in the remote table usb.bas2_agency_to_riskrate_repos#ofsadev or a local version of the same. Use the appropriate table inside NOT EXISTS to do the comparison.
CREATE OR REPLACE PROCEDURE usb.basel2_riskrating AS
BEGIN
INSERT INTO usb.bas2_agency_to_riskrate_repos#ofsadev
SELECT * FROM usb.bas2_agency_to_riskrating_tran m
WHERE NOT EXISTS ( select 1 from
usb.bas2_agency_to_riskrate_repos e --#ofsadev?
where e.as_of_date = m.as_of_date
);
COMMIT; --Try to avoid commits inside procedure, move it to execution section
END basel2_riskrating;
SELECT * FROM USB.BAS2_AGENCY_TO_RISKRATING_TRAN M WHERE USB.BAS2_AGENCY_TO_RISKRATE_REPOS.AS_OF_DATE != M.AS_OF_DATE ;
is wrong. You can not run such a select against DB, it has no USB.BAS2_AGENCY_TO_RISKRATE_REPOS in from clause
Is following statement from doc: valid?
If you exit a stored subprogram with an unhandled exception, PL/SQL
does not assign values to OUT parameters, and does not do any rollback
As per the statement ROLLBACK should not happen when my stored procedure testy raise an exception unhandled. And as per document insert 3, insert 2 should be successful, but no insert are successful.
create table mytable (num int not null primary key);
insert into mytable values(1);
create or replace procedure testy is
begin
insert into mytable values(2);
insert into mytable values(1); //throws error: ORA-00001: unique constraint (SRISRI1.SYS_C0011447) violated
end;
create or replace procedure testp is
begin
insert into mytable values(3);
testy;
insert into mytable values(4);
end;
exec testp;
select * from mytable;
mytable
_______
1
We've discussed it in your previous topic, haven't we?
William Robertson said:
You can think of the whole anonymous block as behaving like a single
DML statement. If it fails, it rolls back to its own start, just like
an update etc.
you inserted value "1" via INSERT INTO statement
then you called TESTP which
inserted "3"
called TESTY which
inserted "2"
tried to insert "1" but failed
Oracle performed an implicit rollback and reverted INSERT 2 and INSERT 3, which returns you back to the starting point, i.e. to a situation you've had before executing the TESTP procedure, and that is value 1 in the table.
I've created one of many stored procedures as part of an ETL process and one of the queries within a stored procedure isn't executing.
The environment is SQL Server 2012 SP2.
The bizarre thing is this -
Run the select part of the insert (affected query) - returns rows
Run the insert (affected query) - inserts rows
Run the whole stored procedure via SSMS - inserts rows
Run via SSIS - all other queries run barring the one of concern!
There are no conditions in my stored procedure e.g. if x = True the Return and no debug code is in there either e.g. return. There are also no transactions and the table I am reading from is a staging table populated prveiously by a data flow.
The query:
INSERT INTO Person.CustomerLinks
(PersonID, SystemID, CustomerID_bin, CustomerActive)
SELECT i.PersonID
, s.SystemDefID
, i.CustomerID_bin
, 0
FROM Staging.IdentifyOutput i
JOIN Config.SystemDef s ON s.OutputType = i.OutputType
WHERE i.CustomerID_bin IS NOT NULL
AND i.OutputType IN ('L', 'X')
AND i.PersonID > 0
AND i.FileDuplicate = 1
AND i.PreferredRecord = 1
AND NOT EXISTS ( SELECT 1
FROM Person.CustomerLinks cl
WHERE cl.PersonID = i.PersonID
AND cl.CustomerID_bin = i.CustomerID_bin)
The procedure has a Try Catch block and the Catch will raise an error and no error is raised.
The only other non ETL code in the procedure is -
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
But I put this in all of my procedures in this application as I am not concerned about dirty reads as they won't happen.
I placed tsql directly after the insert to write to my audit system and ##RowCount was 0. Yet if I run the select now I get over 1.5 million rows back.
Any suggestions?
If you are using a Execute T-SQL task then please try replacing it with the Execute SQL Task.
I don't know what caused it, but I moved the specific SQL into another stored procedure and it worked. In reality, it warranted being in its own stored procedure by right as it was only semi related to the procedure in question.