SQL & PL/SQL :: Returning Old Value During Update?
Jan 2, 2012
In a pl/sql procedure, when I am doing an update, I need the old value to be returned and stored in a local variable, so that the same can be used for future purpose.
Note : I know the "OLD:" option is present when we use TRIGGER, but in my case , the table I am updating is a old table and I am not permitted to create a trigger for it.
I've just started with the Oracle SQL and come from a heavy MS SQL background and I understand that here are some natural differences in the syntax but I'm stumped as to why the following sql represents a problem:
update MASTERMICODES t1 set t1.TEMPTA = ( select t2.TAFCODE from TA_FEATURES t2 where t2.FCODE = t1.FCODE )
It returns Error report: SQL Error: ORA-01427: single-row subquery returns more than one row 01427. 00000 - "single-row subquery returns more than one row" *Cause: *Action:
I want it to return more than one row...in fact I want it to make on all rows that have the same fcode between tables.
This is a surprisingly common one I've found on the web...even on devshed forum
I am updating one table from another (Updating Table A from Table B):
Table A ID, Value -- ----- 1 A 1 A 2 B
Table B ID, Value -- ----- 1 Animal 2 Box
Table A (modified) ID, Value, Name 1 A Animal 1 A Animal 2 B Box
No I need to update a new column in Table A with the value in Table B.Value where the ID's from both tables match. Problem is: When I do this I get multiple rows and hence Oracle won't let me update this column. Now, I keep reading that for these types of updates, there has to be a one-to-one relationship...
Is this true...is there anyway of telling Oracle to update wherever it finds that ID, regardless of how many duplicate ID's there are?
This is quite a frustrating problem and most of the sites that I've looked for solutions try get the query one-to-one...problem is...with my table sets it's impossible to do that - I need to update wherever the id's match (even if it return multiple rows).
want to update 230 records in ins_spr table but its returning error..
Sql statement in blue color returning 230 records.
------------------------------------------------ update ins_spr set SPR_EXCC = 'NORSk' where spr_code = (select distinct spr_code from ins_spr where spr_levc = 'N' and spr_facc = 'ROS' and (sts_code = 'AP' or sts_code = 'LS') and spr_stuc in (select distinct a.sqe_stuc from srs_sqe a where a.SQE_EQEC = 'NP3M' and a.SQE_SQSC = 'BE' and a.sqe_stuc in ( select distinct b.sqe_stuc from srs_sqe b where a.sqe_stuc=b.sqe_stuc and SQE_EQEC = 'NP3S' and SQE_SQSC = 'BE')))
OR
update ins_spr set SPR_EXCC = 'NORSK' where spr_code = (select spr_code from ins_spr where spr_levc = 'N' and spr_facc = 'ROS' and (sts_code = 'AP' or sts_code = 'LS') and exists (select sqe_stuc from srs_sqe a where sqe_stuc = substr(spr_code,1,8) and SQE_EQEC = 'NP3M' and SQE_SQSC = 'BE' and exists ( select sqe_stuc from srs_sqe b where a.sqe_stuc=b.sqe_stuc and SQE_EQEC = 'NP3S' and SQE_SQSC = 'BE')))
create table testing ( id number (10), key number (10) ) insert into testing values (1,10) insert into testing values (1,10) insert into testing values (2,10) insert into testing values (2,20) insert into testing values (3,10)
i got a table(deptid, deptname, address,city,zip, state, other columns) i want to write a query to determine any error(records with different values) because i expect all records grouped-by(deptid, deptname, address,city,zip, state) to have the same deptid(pls note that deptid isnt unique),
or a specific deptid should have only one record based on the grouping (deptid, deptname, address,city,zip, state),
I have a table which lists previous jobs, whcih has monthto,yearto, monthfrom and year from fields. I am trying to find the most recent job (of which they might be multiple ending on the same month) Initially, i did the following:
ran a sub query to find the most recent (employee id, max (yearto * 12 + monthto), then another query where I got a list of the most recent jobs, and returned the first one using rownum = 1 (note this may be inconsistent between runs as thee rownum is calculcated before nay ordering clause. This worked, but i figured using the first function might be better as it gives an order
select employee_id from (select employee_id ,max(NVL(yearto,0) *12 + NVL(monthto,1)) KEEP (DENSE_RANK FIRST ORDER BY emloyer) as latest from employees group by employee_id;
but this seems to return more than one entrty:
table date below: drop table employee_list; drop table employee_historic; [code]...
What is the best way to return a single row, if the primary key is not available / applicable.
I am working on a script in which I want to retrieve multiple rows but I get error ORA-1422.I tried solving it using the following script , but it still gives error.
CREATE OR REPLACE PROCEDURE proc_query DECLARE TYPE all_dest IS TABLE OF NUMBER; destIds all_dest; BEGIN SELECT dest_id from sb_packet WHERE src_id = 32; RETURNING dest_id bulk collect into destIds; END;
For the customer ID 123 I want to return Z1, for customer 678 I want to return S2 and for customer ID 345 I want 11
Problem is that I'm new to the concept of looping. I know how to write a function that accepts customer_id as a value write a cursor and then check IF hierarchy = 1 the return FUNCTION_CODE IF hierarchy - 2 THEN ...
but I need something more universal as some of the customers may have hierarchy function 1 and that would be the top one for him but others might have function of hierarchy 10 as top and checking all of the possibilities using if would be just stupid. So how to write something universal ? And of course if function did not find any customer_id then return null.
I need to return which hour for a given date range had the most calls. I have a query that works but it is inelegant and I'm pretty sure I could do better. I'm pretty new to analytic queries so go easy...
select hour, calls from ( select hour, calls, rank() over (ORDER BY calls desc) as ranking from (
I'm trying to query an array where we will have mathnames that have the follow format: variablemathname[00000]
have been digging around for a few days to try and simplify my existing query. As of right now i'm hacking it together to bring back the bracketed array value by using INSTR and SUBSTR. This works and gets me the correct results but I want to clean the code up by using regexp_SUBSTR.
In my reading up on regular expression I've tried to create my pattern by using [.] which I believe to be [any character]. I want it to start at the beginning of the string so I've used [^ and I only want the one occurrence so I've ended my expression with ]
I tried using the escape before my pattern as I know that [ is a metacharacter but I receive the same results.i'm trying to use to get the expression correct.
SELECT REGEXP_SUBSTR('variablemathname[00000]', '[.],[^,],') RESULT FROM DUAL;
My expectation is it will bring back the following [00000] but the way it is written now is bringing back nothing.
I understand what the message "subquery returning multiple rows" means but I have a case where I'm not 100% sure why it's happening to my update query (which in turn probably means I don't fully understand what's going on behind the scenes)
Here is my query:
Update A set (A.id, A.alt_name, A.min_rank)= (SELECT B.id, B.fullname, MIN(B.nm_rankval) FROM B, A WHERE A.id = B.id AND A.name <> B.fullname AND B.nametyp = 'ON' GROUP BY B.id, B.fullname) ;
The subquery returns 6 rows but they are all unique in terms of the id, name, rankval, etc...I naturally thought that the update statement wouldn't have a problem with this since the subquery is returning rows that are not duplicates and match one for one between table A and B. I used the group by to ensure I return unique values from table B (which does have duplicate id values)
Each of those 6 rows from the subquery of table B can be matched 1-1 with table A...so what am I missing.
I work on a client-server application, where users need to be able to run rather complex queries.
We currently have most of the queries defined in views on the Oracle database server and the client application simply downloads the data (i.e. SELECT * from example_view). This is good for us as we can maintain these queries without releasing new versions of the client tool.
However we have some queries implemented by a colleague that have caused a lot of trouble (efficiency and quality) and these are stored client-side.
The issue I have is that these client side queries can return records in different units (i.e. in standard cubic metres, or barrels of oil etc), as the SQL is defined at runtime on the client, and I want to know the best way to replicate this with SQL stored server-side.
The client-side SQL has column definitions such as: SELECT oil_production * decode(&unit,'Nm3',.948,'Sm3',1,'MMBOE',6.0924,1) ... The &unit parameter is then replaced by the appropriate text (i.e. 'Sm3') before the query is sent to Oracle.
Is there anyway to pass variables to server-side SQL and get a recordset back? I don't think PL/SQL procedures can do this? and views can't contain bind variables.
I would like to create some PL/SQL procedures that return XML as CLOB parameters. I want to just do this (which works fine with simple tests):
create or replace procedure p_xml_test_1( p_xml out nocopy clob ) is begin p_xml := '<?xml version="1.0" encoding="utf8" ?>' || '<test><something>some value</something></test>'; end p_xml_test_1;
But I have access to some other source code that basically does this:
create or replace procedure p_xml_test_2( p_xml out nocopy clob ) is lv_xml clob; begin dbms_lob.createtemporary( [code]......
I'm wondering if the first method will cause any problems for me down the road. Is it ok to do it that way? What is the advantage, if any, to the second method?
I'm creating a stored procedure where i get to return (OUT parameter) a cursor that points to a custom table. If I create an object, I could just do something like:
Quote: CREATE OR REPLACE TYPE TmpObjType AS OBJECT (...); CREATE OR REPLACE TYPE TmpObjTblType AS TABLE OF TmpObjType; PROCEDURE tmp_proc (..., out_param_resultset OUT g_cursor_type ) .... OPEN out_param_resultset FOR SELECT * FROM TABLE(CAST(tmpObjTbl AS TmpObjTblType)); ....
How do I return the table (referenced by a cursor) without creating objects?
I have been testing some functionalist, I have been trying to get the updated dept no values into an array and then print the count. But i am getting the following error.
I have implemented, the whole example is to know about 'dynamic sql returning clause into collection'
s@ORCL> select * from t_dept;
DEPTNO DNAME LOC ---------- -------------- ------------- 10 comp NEW YORK 20 Compt DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON 60 Comp Ahaaa 80 data ab 80 data ab 80 data ab 80 data ab
9 rows selected.
s@ORCL> ed Wrote file afiedt.buf
1 declare 2 type tp_dept is table of number; 3 arr_dept tp_dept; 4 begin 5 execute immediate q'['update t_dept set dname = 'Pointers' where deptno = 80 returning deptno into :out]' 6 returning into arr_dept; 7 dbms_output.put_line('The count is '||arr_dept.count); 8* end; s@ORCL> / returning into arr_dept; * ERROR at line 6: ORA-06550: line 6, column 19: PLS-00597: expression 'ARR_DEPT' in the INTO list is of wrong type ORA-06550: line 5, column 4: PL/SQL: Statement ignored
The following code is indicative of what I'd like to do (as in not correct at all ). Would there be a more immediate way to accomplish this other than executing a SELECT statement after the UPDATE?
-- Incorrect indicative example 1.
DECLARE v_cur SYS_REFCURSOR; BEGIN UPDATE table1(f1, f2) SET ('v1', 'v2') WHERE f3 = 'v3' RETURNING <updated_rows> INTO v_cur END;
-- Incorrect indicative example 2.
DECLARE v_cur SYS_REFCURSOR; BEGIN OPEN v_cur FOR UPDATE table1(f1, f2) SET ('v1', 'v2') WHERE f3 = 'v3' END;
using dbms_profiler for a package having procedure returning sys_refcursor.
I have 2 procedure in a package. let say, proc1 and proc2 ( also proc1 is called inside from proc2)
proc1 has no parameter
proc2 has 2 paramter proc2(p_num in integer, p_data out sys_refcursor) [ in which we pass the p_num (ex: 1) and it run to get the data from the tab le and return that data through sys_refcursor.
for proc1, I am able to use dbms_profiler as below and it is working fine
I am trying to use utl_tcp to connect, through TCP/IP, to a 3rd party program PC Miler. When I use telnet, PC Miler works without any issue. However, when I use utl_tcp, beginning from the second PC Miler API call, when I do a utl_tcp.get_line to get the result, the first line that return is always blank (with 1 white space). Here is my program.
--------------------------------------------------- DECLARE c utl_tcp.connection; ret_val PLS_INTEGER; v_data VARCHAR2(4000); BEGIN c := utl_tcp.open_connection('mars', 8145);
[code]....
Note that the 1st and 3rd API call is the same and should give me the same results. The 2nd API is supposed to give me 1 line back. At the end of each output, the server will end will the word "Ready". I use that to indicate when to exit the loop.
If I disconnect and reconnect after each API call, each output result will be correct because each API call will become the "1st" call since connection - like this program:
DECLARE c utl_tcp.connection; ret_val PLS_INTEGER; v_data VARCHAR2(4000); BEGIN c := utl_tcp.open_connection('mars', 8145);
[code]....
If there is something wrong with PC Miler, why would it work when I telnet through a Windows Command prompt? If it is not PC Miler and utl_tcp, what else can be wrong?
Update employee e set e.dept_id = (select d.dept_id from dept d
[Code].....
The above is not the exact code which I am executing but an exact replica of the logic implied in my code.
Now, when i display the value of 'rows_updated' it returns a value greater than 0,i.e 3 but it should ideally return 0 since there are no records matching for the condition: (select d.dept_id from dept d where e.dept_name = d.dept_name)
So, I executed the statement: select count(*) from employee e where emp_id = 1234 and exists (select 1 from emp_his ee where e.emp_id = ee.emp_id) and the result was 3 which is the same value returned by %rowcount.
why this is happening as I am getting incorrect values in %rowcount for the number of rows updated.
I am creating a db function to select * from table_name to be used by the application for retrieving lookup data. I found many examples for how to return cursor as a result of executing a dynamic sql but don't know the optimum way.
following is my current trial:
CREATE OR REPLACE PACKAGE types AS TYPE Cursortype IS REF CURSOR; END; /
CREATE OR REPLACE FUNCTION F_GEN_SELECT_CURS (S_APP_USER IN VARCHAR2, I_MODULE_ID IN NUMBER, S_TABLE IN VARCHAR2) /*This function maps S_ACC_MAJOR_ACCOUNT_LIST CoolGen service [code].......
I have a stored procedure that is returning no data. I have read this is most common in stored procedures that use a SELECT INTO that tries to put a null in the variable.First, the stored procedure (from SQL Developer) then th execute and error.
PROCEDURE prc_add_address (addr_id OUT integer, addr_type_id IN integer, addr_line_1 IN varchar2, addr_line_2 IN varchar2 := null, addr_line_3 IN varchar2 := null, prov IN varchar2 := null, zip_id IN number, country_cd IN varchar2 := 'USA', addr_start_date IN date, addr_end_date IN date := null, changed_by IN varchar2, changed_date IN date, channel_txt IN varchar2 := null)
[code]....
The sad conclusion:
Error starting at line 1 in command: declare addrid integer := 0; BEGIN pkg_vic_person.PRC_ADD_ADDRESS (addrid, addr_type_id => 1, addr_line_1 => '351437 Tall Blvd', zip_id => 14906, addr_start_date => '01-FEB-2011', changed_by => 'RS', changed_date => sysdate);
I have the following function that I am using as a template for any function that executes a select statement and return a single value as an output.
The function is working but I wanted to take an expert opinion if it can be optimized.
CREATE OR REPLACE FUNCTION AFESD.F_AGR_GET_AGREEMENT_SERIAL (I_NUMBER0 IN NUMBER, S_SUB_NUMBER VARCHAR2 DEFAULT NULL, I_TYPE_ID NUMBER)
[Code]....
In addition I want to use the parameter S_SUB_NUMBER that can be NULL and add it to the select statement of the cursor, but I dont know how to do that in one statement.
CURSOR C_AGREEMENT IS SELECT AGREEMENT_SERIAL FROM VW_AGR_AGREEMENT WHERE NUMBER0 = I_NUMBER0 AND TYPE_ID = I_TYPE_ID -->and sub_number is null; -->and sumb_number = s_sub_number
select * from t_act_rwrd_reimb_stay a where reimbursed_amt < 0 and invoice_date = '01-JAN-1900' and not exists ( select 'x' from t_act_rwrd_reimb_stay b where a.GPM_ID_STAY = b.GPM_ID_STAY and reimbursed_amt > 0 )
The above table t_act_rwrd_reimb_stay --> is from a view on the database Prod2 and this view is pulling the data from the database prod1 via dblink
When I run the same query on Prod1 it returns 3 rows. Is there any reason this is not fetching data on prod2 view? or whatz wrong with the above query
or for example if I run the above query as follows with the dblink "@prod1" it returns the data properly
select * from t_act_rwrd_reimb_stay@Prod1 a where reimbursed_amt < 0 and invoice_date = '01-JAN-1900' and not exists ( select 'x' from t_act_rwrd_reimb_stay@prod1 b where a.GPM_ID_STAY = b.GPM_ID_STAY and reimbursed_amt > 0 )