Use of ROWID in SQL Update Statement
Hi All,
I have an update statement which uses the rowid column to perform the selection on the target table. Given that a rowid represents the physical location of a row on disk we know that this reference can change when various activities are performed on the database/table/row etc...
Here is an example of the statement I am issuing:
UPDATE tabA outertab SET col1 = 'Value'
WHERE EXISTS (SELECT 1 FROM tabA innertab WHERE outertab.ROWID = outertab.ROWID AND ...)
Obviously the inner query is more complicated and uses other tables etc... but for the purposes of the example we dont need to include the detail.
My question is: When using rowid in a single SQL statement as a reference from a subquery to the outer statement is there a risk that external activities can change the rowid and those changes be reflected within the database session that my query is executing thus causing an inconsistency between the inner and outer SQL clause?
In response to the question which will follow this post: "Why don't you just use a PK", We would like to avoid maintaining a PK on the table as we are talking about very large volumes of data and we dont want to have to issue a call to a sequence if we can avoid it when we are inserting the data. If however there is a risk that this Update statement could fail or update the wrong rows then we may have to use a PK.
I know there is a lot of threads about this but I havnt been able to find one that someone has answered with any kind of confidence or clarity, any help would be much appreciated.
Thanks
Keith
Edited by: The Turtle on Mar 5, 2009 5:24 AM
When using rowid in a single SQL statement as a reference from a subquery to the outer statement is there a risk that external activities can change the rowid and those changes be reflected within the database session that my query is executing thus causing an inconsistency between the inner and outer SQL clause?No, it's safe to use rowid in this type of query. Docs
A row's assigned rowid remains unchanged unless the row is exported and imported using the Import and Export utilities. When you delete a row from a table and then commit the encompassing transaction, the deleted row's associated rowid can be assigned to a row inserted in a subsequent transaction.
Similar Messages
-
Using named parameters with an sql UPDATE statement
I am trying to write a simple? application on my Windows 7 PC using HTML, Javascript and Sqlite. I have created a database with a 3 row table and pre-populated it with data. I have written an HTML data entry form for modifying the data and am able to open the database and populate the form. I am having trouble with my UPDATE function. The current version of the function will saves the entry in the last row of the HTML table into the first two rows of the Sqlite data table -- but I'm so worn out on this that I can't tell if it is accidental or the clue I need to fix it.
This is the full contents of the function . . .
updateData = new air.SQLStatement();
updateData.sqlConnection = conn;
updateData.text = "UPDATE tablename SET Gsts = "Gsts, Gwid = :Gwid, GTitle = :GTitle WHERE GId = ":GId;
var x = document.getElementsById("formname");
for (var i = 1, row, row = x.rows[i]; i++) {
updateData.parameters[":GId"] = 1;
for (var j = 0, col; col=row.cells[j]; j++) {
switch(j) {
case 0: updateData.parameters[":GTitle"] = col.firstChild.value; break;
case 1: updateData.parameters[":Gsts"] = col.firstChild.value; break;
case 2: updateData.parameters[":Gwid"] = col.firstChild.value; break;
Note: When I inspect the contents of the col.firstChild.value cases, they show the proper data as entered in the form -- it just isn't being updated into the proper rows of the Sqlite table.
Am I using the named parameters correctly? I couldn't find much information on the proper use of parameters in an UPDATE statement.Thank you for the notes. Yes, the misplaced quotes were typos. I'm handtyping a truncated version of the function so I don't put too much info in the post. And yes, i = 1 'cuz the first rows of the table are titles. So the current frustration is that I seem to be assigning all the right data to the right parameters but nothing is saving to the database.
I declare updateData as a variable at the top of the script file
Then I start a function for updating the data which establishes the sql connection as shown above.
The correctly typed.text statement is:
updateData.text = "UPDATE tablename SET Gsts=:Gsts, Gwid=:Gwid, GTitle=:GTitle WHERE GId=:GId";
(The data I'm saving is entered in text boxes inside table cells.) And the current version of the loop is:
myTable = document.getElementById("GaugeSts");
myRows= myTable.rows;
for(i=1, i<myRows.length, i++) {
updateData.parameters[":GId"]=i;
for(j=0; j<myRows(i).cells.length, j++) {
switch(y) {
case 0: updateData.parameters[":GTitle"]=myrows[i].cells[y].firstChild.value; break;
case 1: updateData.parameters[":Gsts"]=myrows[i].cells[y].firstChild.value; break;
case 2: updateData.parameters[":Gwid"]=myrows[i].cells[y].firstChild.value; break;
updateData.execute;
The whole thing runs without error and when I include the statements to check what's in myrows[i].cells[y].firstChild.value, I'm seeing that the correct data is being picked up for assignment to the parameters and the update. I haven't been able to double check that the contents of the parameters are actually taking the data 'cuz I don't know how to extract the data from the parameters. ( The only reference I've found so far has said that it is not possible. I'm still researching that one.) I've also tried moving the position of the updateData execution statement to several different locations in the loop andstill nothing updates.
I am using a combination of air.Introspector.Console.log to check the results of code and I'm using Firefox's SQlite manager to handle the database. The database is currently sitting on the Desktop to facilitate testing and I have successfully updated/changed data in this table through the SQLite Manager so I don't think I'm having permission errors and, see below, I have another function successfully saving data to another table.
I currently have another function that uses ? for the parametersin the .text of a INSERT/REPLACE statement and that one works fine. But, only one line of data is being saved so there is no loop involved. I tried changing the UPDATE statement in this function to the INSERT/REPLACE just to make something save back to the database but I can't make that one work either.I've a (And, I've tried so many things now, I don't even remember what actually saved something --albeit incorrectly --to the database in one of my previous iterations with the for loops.)
I'm currently poring through Sqlite and Javascript tomes to see if I can find what's missing but if anything else jumps out at you with the corrected code, I'd appreciate some ideas.
Jeane -
Updates using single SQL Update statement.
Hi Guys,
I had an interview... and was not able to give an answer of one of the question.
Given the emp table... need to update the salary with following requirement using one SQL statement...
1. Update salary+1000 for those employees who have salary between 500 and 1000
2. Update salary+500 for those employees who have salary between 1001 and 1500
Both above requirement should be done by using only one SQL update statement... can some one tell me how to do it?update emp
set salary = case when salary between 500 and 1000
then salary + 1000
when salary between 1001 and 1500
then salary + 500
end;Regards
Arun -
SQL UPDATE Statement Explaination (urgent please...)
Hi,
Could anyone explain for me what this statement will do:
update KPIR KR
set ( CA ) = (
select sum(sl.RRC_CONN_STP_ATT) CA
from PV_WCEL_SERVICE_LEVEL sl, UTP_MO um
where sl.GLOBAL_ID = um.CO_GID
group by sl.STARTTIME, um.OBJECT_INSTANCE
I could not understand how the mapping between the two tables will be ("um" clause is not used in the select statement and it is used only in the "where" and "group by" arguments) What does this mean?.
The actual problem is that when I execute the above SQL statement, it was take around just 3 minutes to be implemented. But after we upgrade from Oracle 8 to Oracle 9, this statement is taking around 3 hours to be implemented.
Anyone have any idea what is the problem?Below is the plan:
KPIR table:
RNC_ID (str), PST ('YYYYMMDD_HH24'), CA (Numner)
1, 20061105_13, 0
1, 20061105_14, 0
1, 20061105_15, 0
2, 20061105_13, 0
2, 20061105_14, 0
2, 20061105_15, 0
3, 20061105_13, 0
3, 20061105_14, 0
3, 20061105_15, 0
4, 20061105_13, 0
4, 20061105_14, 0
4, 20061105_15, 0
PV_WCEL_SERVICE_LEVEL table:
GLOBAL_ID (str), STARTTIME ('YYYYMMDD_HH24'), RRC_CONN_STP_ATT (Number)
A1, 20061101_00, 9
A1, 20061101_01, 4
A1, 20061101_23, 3
A1, 20061130_23, 4
A2, 20061101_00, 3
A2, 20061101_01, 4
A2, 20061101_23, 1
A2, 20061130_23, 5
UTP_MO table;
RNC_ID (str), GLOBAL_ID (str), OBJECT_INSTANCE (str)
1, A1, <A1_NAME>
1, A2, <A2_NAME>
1, A9, <A9_NAME>
2, B1, <B1_NAME>
2, B2, <B2_NAME>
2, B9, <B9_NAME>
3, C1, <C1_NAME>
3, C2, <C2_NAME>
3, C9, <C9_NAME>
4, D1, <D1_NAME>
4, D2, <D2_NAME>
4, D9, <D9_NAME>
Now, I want to update the value of CA in table KPIR:
For instance, for RNC_ID='1' and at PST='20061105_13', the CA should equals to the sum of value RRC_CONN_STP_ATT for all GLOBAL_IDs under RNC_ID='1' and at STARTTIME '20061105_13'.
So, is this SQL UPDATE statement will do it?
update KPIR kr
set ( CA ) = (
select sum(sl.RRC_CONN_STP_ATT) CA
from PV_WCEL_SERVICE_LEVEL sl, UTP_MO um
where sl.GLOBAL_ID = um.GLOBAL_ID and kr.RNC_ID = um.RNC_ID and kr.PST = sl.STARTTIME
group by sl.STARTTIME, um.OBJECT_INSTANCE
And if so, why it is taking around 3 hours to be implemented? This issue is happened after upgrading from Oracle 8 to 9.
Really appreciate your help and thanks in advance. -
Regex help for SQL update statement
Hello,
need help from IPS regex guru - trying to build the signature to detect SQL update statement in HTTP requests.
1) Am I correct with regex below specified as Request-Regex?
[Uu][Pp][Dd][Aa][Tt][Ee]([%]20|[+])[\x20-\x7e]+[Ss][Ee][Tt]([%]20|[+])[\x20-\x7e]+=
2) How do I make sure that it detects 'Update' in URI and Arguments only and not in the body on entire webserver response (currently looks like the case)?1) It looks correct to me
2) Typically, the "service HTTP" engine is used to inspect requests and the "TCP string" engine is used to inspect HTTP server responses. If you only want to inspect requests, use the service HTTP engine. -
How can i use multiple row subquery in update statement
Hai All
I using group function in my update statement.. and i need to update more rows so i need to use multiple row
subquery pls tell me how to use multiple row subquery in update statement
For example
while i am using this like this i got an error
update dail_att set outtime in (select max(r2.ptime) from temp_att where empcode=r2.enpno and
barcode=r2.cardn and attend_date=r2.pdate group by enpno,pdate,cardn);
Pls tell me how to use with example
Thanks & regards
Srikkanth.MHai Man
Thanks for ur response Let me clear what i need
First step Fetch the records as text file and stores into table T1
and the next step is i have seperated the text using substring and stores in different columns of a table
There are two shifts 0815 to 1645 and 1200 and 2000
Here I rep IN and O rep OUT
Empno date time inout
001 01-01-10 0815 I
002 01-01-10 0815 I
003 01-01-10 0818 I
001 01-01-10 1100 0
001 01-01-10 1130 I
002 01-01-10 1145 0
002 01-01-10 1215 I
004 01-01-10 1200 I
005 01-01-10 1215 I
004 01-01-10 1315 O
004 01-01-10 1345 I
001 01-01-10 1645 0
002 01-01-10 1715 0
003 01-01-10 1718 0
004 01-01-10 2010 0
005 01-01-10 2015 0
This is my T1 table i have taken data from text file and stored in this table from this table i need to move data to another table T2
T2 contains like this
Empno Intime Intrin Introut Outtime Date
001 0815 1100 1130 1645 01-01-10
002 0815 1145 1215 1715 01-01-10
003 0818 1718 01-01-10
004 1200 1315 1345 2010 01-01-10
005 1215 2015 01-01-10
This what i am trying to do man but i have little bit problems Pls give some solution with good example
And my coding is
declare
emp_code varchar2(25);
in_time varchar2(25);
out_time varchar2(25);
Cursor P1 is
Select REASON,ECODE,READMODE,EMPD,ENPNO,FILL,PDATE,PTIME,INOUT,CARDN,READERN
From temp_att
group by REASON,ECODE,READMODE,EMPD,ENPNO,FILL,PDATE,PTIME,INOUT,CARDN,READERN
ORDER BY enpno,pdate,ptime;
begin
for r2 in p1 loop
declare
bar_code varchar2(25);
begin
select barcode into bar_code from dail_att where empcode=r2.enpno and attend_date=r2.pdate;
For r3 in (select empcode,empname,barcode,intime,intrin,introut,addin,addout,outtime,attend_date from dail_att)loop
if r2.inout ='O' then
update dail_att set outtime =(select max(r2.ptime) from temp_att where empcode=r2.enpno and barcode=r2.cardn and attend_date=r2.pdate group by r2.cardn,r2.enpno,r2.pdate );
end if;
end loop;
exception
when no_data_found then
if r2.inout ='I' then
insert into dail_att(barcode,empcode,intime,attend_date)(select r2.cardn,r2.enpno,min(r2.ptime),r2.pdate from temp_att group by r2.cardn,r2.enpno,r2.pdate );
end if;
end;
end loop;
commit;
end;
Pls tell me what correction i need to do i the update statement i have used a subquery with group function but when i used it will return only one row but my need is to return many rows and i need to use multiple row subquery
and how can i use it in the update statement
Thanks In Advance
Srikkanth.M -
SQL Update statement taking too long..
Hi All,
I have a simple update statement that goes through a table of 95000 rows that is taking too long to update; here are the details:
Oracle Version: 11.2.0.1 64bit
OS: Windows 2008 64bit
desc temp_person;
Name Null? Type
PERSON_ID NOT NULL NUMBER(10)
DISTRICT_ID NOT NULL NUMBER(10)
FIRST_NAME VARCHAR2(60)
MIDDLE_NAME VARCHAR2(60)
LAST_NAME VARCHAR2(60)
BIRTH_DATE DATE
SIN VARCHAR2(11)
PARTY_ID NUMBER(10)
ACTIVE_STATUS NOT NULL VARCHAR2(1)
TAXABLE_FLAG VARCHAR2(1)
CPP_EXEMPT VARCHAR2(1)
EVENT_ID NOT NULL NUMBER(10)
USER_INFO_ID NUMBER(10)
TIMESTAMP NOT NULL DATE
CREATE INDEX tmp_rs_PERSON_ED ON temp_person (PERSON_ID,DISTRICT_ID) TABLESPACE D_INDEX;
Index created.
ANALYZE INDEX tmp_PERSON_ED COMPUTE STATISTICS;
Index analyzed.
explain plan for update temp_person
2 set first_name = (select trim(f_name)
3 from ext_names_csv
4 where temp_person.PERSON_ID=ext_names_csv.p_id
5 and temp_person.DISTRICT_ID=ext_names_csv.ed_id);
Explained.
@?/rdbms/admin/utlxpls.sql
PLAN_TABLE_OUTPUT
Plan hash value: 3786226716
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | UPDATE STATEMENT | | 82095 | 4649K| 2052K (4)| 06:50:31 |
| 1 | UPDATE | TEMP_PERSON | | | | |
| 2 | TABLE ACCESS FULL | TEMP_PERSON | 82095 | 4649K| 191 (1)| 00:00:03 |
|* 3 | EXTERNAL TABLE ACCESS FULL| EXT_NAMES_CSV | 1 | 178 | 24 (0)| 00:00:01 |
Predicate Information (identified by operation id):
3 - filter("EXT_NAMES_CSV"."P_ID"=:B1 AND "EXT_NAMES_CSV"."ED_ID"=:B2)
Note
- dynamic sampling used for this statement (level=2)
19 rows selected.By the looks of it the update is going to take 6 hrs!!!
ext_names_csv is an external table that have the same number of rows as the PERSON table.
ROHO@rohof> desc ext_names_csv
Name Null? Type
P_ID NUMBER
ED_ID NUMBER
F_NAME VARCHAR2(300)
L_NAME VARCHAR2(300)Anyone can help diagnose this please.
Thanks
Edited by: rsar001 on Feb 11, 2011 9:10 PMThank you all for the great ideas, you have been extremely helpful. Here is what we did and were able to resolve the query.
We started with Etbin's idea to create a table from the ext table so that we can index and reference easier than an external table, so we did the following:
SQL> create table ext_person as select P_ID,ED_ID,trim(F_NAME) fst_name,trim(L_NAME) lst_name from EXT_NAMES_CSV;
Table created.
SQL> desc ext_person
Name Null? Type
P_ID NUMBER
ED_ID NUMBER
FST_NAME VARCHAR2(300)
LST_NAME VARCHAR2(300)
SQL> select count(*) from ext_person;
COUNT(*)
93383
SQL> CREATE INDEX EXT_PERSON_ED ON ext_person (P_ID,ED_ID) TABLESPACE D_INDEX;
Index created.
SQL> exec dbms_stats.gather_index_stats(ownname=>'APPD', indname=>'EXT_PERSON_ED',partname=> NULL , estimate_percent=> 30 );
PL/SQL procedure successfully completed.We had a look at the plan with the original SQL query that we had:
SQL> explain plan for update temp_person
2 set first_name = (select fst_name
3 from ext_person
4 where temp_person.PERSON_ID=ext_person.p_id
5 and temp_person.DISTRICT_ID=ext_person.ed_id);
Explained.
SQL> @?/rdbms/admin/utlxpls.sql
PLAN_TABLE_OUTPUT
Plan hash value: 1236196514
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | UPDATE STATEMENT | | 93383 | 1550K| 186K (50)| 00:37:24 |
| 1 | UPDATE | TEMP_PERSON | | | | |
| 2 | TABLE ACCESS FULL | TEMP_PERSON | 93383 | 1550K| 191 (1)| 00:00:03 |
| 3 | TABLE ACCESS BY INDEX ROWID| EXTT_PERSON | 9 | 1602 | 1 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | EXT_PERSON_ED | 1 | | 1 (0)| 00:00:01 |
Predicate Information (identified by operation id):
4 - access("EXT_PERSON"."P_ID"=:B1 AND "RS_PERSON"."ED_ID"=:B2)
Note
- dynamic sampling used for this statement (level=2)
20 rows selected.As you can see the time has dropped to 37min (from 6 hrs). Then we decided to change the SQL query and use donisback's suggestion (using MERGE); we explained the plan for teh new query and here is the results:
SQL> explain plan for MERGE INTO temp_person t
2 USING (SELECT fst_name ,p_id,ed_id
3 FROM ext_person) ext
4 ON (ext.p_id=t.person_id AND ext.ed_id=t.district_id)
5 WHEN MATCHED THEN
6 UPDATE set t.first_name=ext.fst_name;
Explained.
SQL> @?/rdbms/admin/utlxpls.sql
PLAN_TABLE_OUTPUT
Plan hash value: 2192307910
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
| 0 | MERGE STATEMENT | | 92307 | 14M| | 1417 (1)| 00:00:17 |
| 1 | MERGE | TEMP_PERSON | | | | | |
| 2 | VIEW | | | | | | |
|* 3 | HASH JOIN | | 92307 | 20M| 6384K| 1417 (1)| 00:00:17 |
| 4 | TABLE ACCESS FULL| TEMP_PERSON | 93383 | 5289K| | 192 (2)| 00:00:03 |
| 5 | TABLE ACCESS FULL| EXT_PERSON | 92307 | 15M| | 85 (2)| 00:00:02 |
Predicate Information (identified by operation id):
3 - access("P_ID"="T"."PERSON_ID" AND "ED_ID"="T"."DISTRICT_ID")
Note
- dynamic sampling used for this statement (level=2)
21 rows selected.As you can see, the update now takes 00:00:17 to run (need to say more?) :)
Thank you all for your ideas that helped us get to the solution.
Much appreciated.
Thanks -
Sql Update Statement (complex)
Hi ,
A very good morning to all.
I am stuck in a problem , and i really hope for solutiion.
I have a dimension table (DIM_CAR) for which i need to write a update statement.
My table structure is :
C_ID Startdate EndDate
7546343 2012-05-29 00:00:00 NULL
7546343 2012-05-18 00:00:00 2012-05-29 00:00:00
7546343 2012-05-14 00:00:00 2012-05-18 00:00:00
7546343 2012-05-10 00:00:00 2012-05-10 00:00:00
7546343 2012-05-10 00:00:00 2012-05-14 00:00:00
7546343 2012-03-22 00:00:00 2012-03-22 00:00:00
7546343 2012-03-15 00:00:00 2012-03-22 00:00:00
7546343 2012-02-02 00:00:00 2012-03-15 00:00:00
7546343 2012-01-31 00:00:00 2012-02-02 00:00:00
Now the scenario is Whenever any update comes in car , then it closes the previous record and open a new record(SCD)
For e.g the 1st update comes on 2012-02-02 , so it closes the last record (by putting 2012-02-02) in end date and open a new record by putting 2012-02-02 in startdate. Then update comes in 2012-03-15 and so on. The last record is for 2012-05-29 which is
still open as there is no update after that,
so whenever any update come it opens a new record with startdate value is extract date and enddate value NULL and closes the previous. Then after another update , that NULL value is replace by the new date and another record opens.
My prob is if you will closely analyse the dates , then there are some records missing in the above table due to which there are discrepencies in dates.
E.g. If u see the 6th row, startdate is 2012-03-22 and enddate is also 2012-03-22. But here in this case the enddate should be 2012-05-10(which is next update)
I need to write a sql script to update enddates with the latest update startdate in my table. I have 60000 of C_id which are affected.
COULD ANYONE plz Help.. I knw its difficult but u can give a try ..........Plz ask if anyone requires more info.
AbhishekPlease post DDL, so that people do not have to guess what the keys, constraints, Declarative Referential Integrity, data types, etc. in your schema are. Learn how to follow ISO-11179 data element naming conventions and formatting rules. Temporal data should
use ISO-8601 formats. Code should be in Standard SQL as much as possible and not local dialect.
This is minimal polite behavior on SQL forums.
>> I have a dimension table (DIM_CAR) for which I need to write a update statement. My table structure is : <<
NO! This is a picture of the data; it is not DDL! Is this what you would have posted if you had manners?
CREATE TABLE Foobars
(c_id CHAR(7) NOT NULL,
foo_start_date DATE NOT NULL,
PRIMARY KEY (c_id, foo_start_date), -- my guess!!
CHECK (foo_start_date < foo_end_date),-- another guess!
foo_end_date DATE);
INSERT INTO Foobar
VALUES
('7546343', '2012-05-29', 'NULL),
('7546343', '2012-05-18', '2012-05-29'),
('7546343', '2012-05-14', '2012-05-18'),
('7546343', '2012-05-10', '2012-05-10'),
('7546343', '2012-05-10', '2012-05-14'),
('7546343', '2012-03-22', '2012-03-22'),
('7546343', '2012-03-15', '2012-03-22'),
('7546343', '2012-02-02', '2012-03-15'),
('7546343', '2012-01-31', '2012-02-02');
Now the scenario is Whenever any update comes in car, then it closes the previous record [sic: rows are not records! Please learn basic terms] and open a new record [sic](SCD).
What is “SCD” and why do you think it is meaningful to us? Here is an article on this topic.
Modifying Contiguous Time Periods
This article explains how to modify contiguous time periods that were described in Joe Celko’s article 'Contiguous Time Periods in SQL'. Joe describes the table itself that he calls the 'Kuznetsov History Table'. He explains how it is used to store contiguous
time intervals with constraint to ensure that the date periods really are contiguous, The editor suggested that I give a brief description of how to modify the data in the History table as this may not be entirely obvious.
When trusted constraints enforce data integrity, the data is guaranteed to be valid at the end of any statement, even if it is not committed. When we modify contiguous time periods, in order to get from one valid state to another we may need to insert a row
and update another one, or we may need to delete a row and update another one. This is one of those cases when MERGE really shines – it allows us to get from one valid state to another in one statement, inserting, updating, and deleting rows as needed.
CREATE TABLE Tasks
(task_id INT NOT NULL,
task_score INTEGER NOT NULL,
current_start_date DATE NOT NULL,
current_end_date DATE NOT NULL,
previous_end_date DATE NULL,
CONSTRAINT PK_Tasks_task_id_current_end_date
PRIMARY KEY (task_id, current_end_date),
CONSTRAINT UNQ_Tasks_task_id_previous_end_date
UNIQUE (task_id, previous_end_date),
CONSTRAINT FK_Tasks_task_id_previous_end_date
FOREIGN KEY (task_id, previous_end_date)
REFERENCES Tasks (task_id, current_end_date),
CONSTRAINT CHK_Tasks_previous_end_date_NotAfter_current_start_date
CHECK (previous_end_date <= current_start_date),
CONSTRAINT CHK_Tasks_current_start_date_Before_current_end_date
CHECK (current_start_date < current_end_date)
Some Easy Modifications.
It is easy to begin a new series of time periods
INSERT INTO Tasks
(task_id, task_score, current_start_date, current_end_date, previous_end_date)
VALUES (1, 100, '2010-1002', '2010-1023', NULL),
(1, 80, '2010-1023', '2010-11-03', '2010-1023');
It is just as easy to continue adding periods to the end of the series.
INSERT INTO Tasks
(task_id, task_score, current_start_date, current_end_date, previous_end_date)
VALUES(1, 98, '2010-11-20', '2010-11-25', '2010-11-03'),
(1, 75, '2010-11-26', '2010-11-27', '2010-11-25');
Deleting one or more rows from the end is just as easy, and we shall skip the example. As we have seen, it is easy to perform typical, the most common operations against history of periods.
However, some other operations are less easy and need more explanations. Now that we have enough test data, let us move on to more complex examples. Here is the test data at this moment:
Adding periods to the beginning.
Each series of periods has exactly one first period – this is enforced by the following constraint: Unique_task_id_and_previous_end_date
As a result, when we are inserting one or more periods to the beginning of the series, we have to update the period that used to be the first, as follows:
MERGE INTO Tasks
USING (VALUES (1, 98, '2009-03-01', '2009-03-06', NULL),
(1, 100, '2010-10-02', '2010-10-23', '2009-03-06')
) AS Source (task_id, task_score, current_start_date, current_end_date, previous_end_date)
ON Tasks.task_id = Source.task_id
AND Tasks.current_start_date = Source.current_start_date
WHEN MATCHED
THEN UPDATE
SET task_score = Source.task_score,
current_start_date = Source.current_start_date,
current_end_date = Source.current_end_date,
previous_end_date = Source.previous_end_date
WHEN NOT MATCHED
THEN INSERT (task_id, task_score, current_start_date, current_end_date, previous_end_date)
VALUES (Source.task_id, Source.task_score, Source.current_start_date,
Source.current_end_date, Source.previous_end_date);
Now we will verify that our test data looks as expected, with a new row at the beginning, and previous_end_date column is modified to point to the new row for the row that used to be the first before this modification:
We are also going to discuss some other scenarios, such as adding/deleting periods in the middle of the series. In all these cases we shall be using MERGE, and the DML looks quite similar, so let us wrap it up in a stored procedure.
CREATING A STORED PROCEDURE
The following code implements this merging functionality with a stored procedure that uses a table to hold teh new rows:
CREATE TABLE NewTasks
(task_id INTEGER NOT NULL,
task_score INTEGER NOT NULL,
current_start_date DATE NOT NULL,
current_end_date DATE NOT NULL,
previous_end_date DATE NULL,
deletion_flg CHAR(1));
CREATE PROCEDURE MergeNewTasks
AS BEGIN
MERGE INTO Tasks
USING (SELECT task_id, task_score, current_start_date, current_end_date, previous_end_date, deletion_flg
FROM NewTasks) AS Source
ON Tasks.task_id = Source.task_id
AND Tasks.current_start_date = Source.current_start_date
WHEN MATCHED AND deletion_flg = 'Y'
THEN DELETE
WHEN MATCHED
THEN UPDATE SET
task_score = Source.task_score,
current_start_date = Source.current_start_date,
current_end_date = Source.current_end_date,
previous_end_date = Source.previous_end_date
WHEN NOT MATCHED
THEN INSERT (task_id, task_score, current_start_date, current_end_date, previous_end_date)
VALUES (Source.task_id, Source.task_score, Source.current_start_date, Source.current_end_date, Source.previous_end_date);
END;
Let us use this stored procedure.
Filling a gap in the middle of the series
The following code fills the gap on November 25th.
CREATE TABLE NewTasks (..);
INSERT INTO NewTasks
(task_id, task_score, current_start_date, current_end_date, previous_end_date, deletion_flg)
VALUES (1, 75, '2010-11-25', '2010-11-26', '2010-11-25', 'N'),
(1, 80, '2010-11-26', '2010-11-27', '2010-11-26', 'N');
EXEC MergeNewTasks NewTasks = NewTasks;
Here is the data after this modification, with a period added in the middle fo the series:
Deleting a period in the middle of the series
The following code deletes the period added in the previous example.
CREATE TABLE NewTasks (..);
INSERT INTO NewTasks
(task_id, task_score, current_start_date, current_end_date,
previous_end_date, deletion_flg)
VALUES (1, 75, '2010-11-25', '2010-11-26', '2010-11-25', 'Y'),
(1, 80, '2010-11-26', '2010-11-27', '2010-11-25', 'N');
EXEC MergeNewTasks;
Here is the data after this modification:
Inserting two periods in the middle, and adjusting an exaisting period to make room for them. This is the last and most complex example involving our stored procedure:
CREATE TABLE NewTasks (..);
INSERT INTO NewTasks
(task_id, task_score, current_start_date, current_end_date, previous_end_date, deletion_flg)
VALUES (1, 98, '2010-11-20', '2010-11-22', '2010-11-03', 'N'),
(1, 75, '2010-11-22', '2010-11-23', '2010-11-22', 'N'),
(1, 98, '2010-11-23', '2010-11-25', '2010-11-23', 'N');
EXEC MergeNewTasks;
--CELKO-- Books in Celko Series for Morgan-Kaufmann Publishing: Analytics and OLAP in SQL / Data and Databases: Concepts in Practice Data / Measurements and Standards in SQL SQL for Smarties / SQL Programming Style / SQL Puzzles and Answers / Thinking
in Sets / Trees and Hierarchies in SQL -
I need to perform bulk updates on my tables using SQL. The tables are really very big and most of updates occur on couple of million records. As such the process is time consuming and very slow. Is there anything I could do to fine tune these update statements? Please advise. Some of the same SQL statements I use are as follows
update test set gid=1 where gid is null and pid between 0 and 1;
update test set gid=2 where gid is null and pid between 1 and 5;
update test set gid=3 where gid is null and pid between 5 and 10;
update test set gid=4 where gid is null and pid between 10 and 15;
update test set gid=5 where gid is null and pid between 15 and 70;
update test set gid=6 where gid is null and pid between 70 and 100;
update test set gid=7 where gid is null and pid between 100 and 150;
update test set gid=8 where gid is null and pid between 150 and 200;
update test set gid=9 where gid is null and pid between 200 and 300;
Message was edited by:
user567669Indeed, check out the predicate:
SQL> explain plan for
2 select *
3 from emp
4 where sal between 1000 and 2000;
Explained.
SQL> @utlxpls
PLAN_TABLE_OUTPUT
Plan hash value: 3956160932
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 5 | 185 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| EMP | 5 | 185 | 3 (0)| 00:00:01 |
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
1 - filter("SAL"<=2000 AND "SAL">=1000) -
How to use User defined Function in Update statement
Hi All,
I have written below update statement to update column based on value return by function. but it is not working. Could any one help me on this. This function will return only one value for each project.
thanks in advance.
UPDATE dg2.OD_PROJ_LOOKUP_TEMP o
SET Months_In_Stage_Cnt = select Months_In_Stage_Cnt_ret(o.project_id) from dual;
thanks
debhi,
CREATE FUNCTION fn_emp_ename (p_empno IN emp.empno%TYPE)
RETURN VARCHAR2
IS
v_ename emp.ename%TYPE;
BEGIN
SELECT ename
INTO v_ename
FROM emp
WHERE empno = p_empno;
RETURN v_ename;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
RETURN NULL;
WHEN OTHERS
THEN
RETURN NULL;
END fn_emp_ename;
SQL>
SQL> select * from emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7369 SMITH CLERK 7902 17-DEC-80 800 20
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7566 JONES MANAGER 7839 02-APR-81 2975 20
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30
7698 BLAKE MANAGER 7839 01-MAY-81 2850 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
7788 SCOTT ANALYST 7566 19-APR-87 3000 20
7839 KING PRESIDENT 17-NOV-81 5000 10
7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30
7876 ADAMS CLERK 7788 23-MAY-87 1100 20
7900 JAMES CLERK 7698 03-DEC-81 950 30
7902 FORD ANALYST 7566 03-DEC-81 3000 20
7934 MILLER CLERK 7782 23-JAN-82 1300 10
14 rows selected.
SQL> select fn_emp_ename (empno) as emp_name from emp;
EMP_NAME
SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER
14 rows selected.
SQL> update emp
2 set ename= fn_emp_ename (7936)
3 where empno=7934;
1 row updated.
SQL> commit;
Commit complete.
SQL> select * from emp where empno=7934;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTN
7934 CLERK 7782 23-JAN-82 1300 1
SQL> i hope this helps .........
Thanks,
P Prakash
Edited by: prakash on Nov 17, 2011 11:52 PM -
How to convert the following FORALL Update to direct SQL UPDATE statement
I have a FORALL loop to update a table. It is taking too long. I want to rewrite the code to a direct UPDATE sql. Also, any other tips or hints which can help run this proc faster?
CURSOR cur_bst_tm IS
SELECT listagg(tm, ' ') WITHIN GROUP(ORDER BY con_addr_id) best_time,
con_addr_id
FROM (select Trim(Upper(con_addr_id)) con_addr_id,
||decode(Initcap(start_day),
'Monday', 'm',
'Tuesday', 'tu',
'Wednesday', 'w',
'Thursday', 'th',
'Friday', 'f',
Initcap(start_day))
||'='
||trunc(( ( TO_DATE(start_tm,'HH12:MI:SS PM') - trunc(TO_DATE(start_tm,'HH12:MI:SS PM')) ) * 24 * 60 ))
||','
||trunc(( ( TO_DATE(end_tm,'HH12:MI:SS PM') - trunc(TO_DATE(end_tm,'HH12:MI:SS PM')) ) * 24 * 60 )) tm
FROM (SELECT DISTINCT * FROM ODS_IDL_EDGE_OFFC_BST_TM)
WHERE con_addr_id is not null)
GROUP BY con_addr_id
ORDER BY con_addr_id;
TYPE ARRAY IS TABLE OF cur_bst_tm%ROWTYPE;
l_data ARRAY;
BEGIN
OPEN cur_bst_tm;
LOOP
FETCH cur_bst_tm BULK COLLECT INTO l_data LIMIT 1000;
FORALL i IN 1..l_data.COUNT
UPDATE ODS_CONTACTS_ADDR tgt
SET best_times = l_data(i).best_time,
ODW_UPD_BY = 'IDL - MASS MARKET',
ODW_UPD_DT = SYSDATE,
ODW_UPD_BATCH_ID = '0'
WHERE Upper(edge_id) = l_data(i).con_addr_id
AND EXISTS (SELECT 1 FROM ods_idl_edge_cont_xref src
WHERE tgt.contacts_odw_id = src.contacts_odw_id
AND src.pc_flg='Y')
EXIT WHEN cur_bst_tm%NOTFOUND;
END LOOP;
CLOSE cur_bst_tm;Record count:-
select count(*) from
ODS_IDL_EDGE_OFFC_BST_TM;
140,000
SELECT count(*)
FROM ods_idl_edge_cont_xref src
WHERE src.pc_flg='Y';
118,000
SELECT count(*)
FROM ODS_CONTACTS_ADDR;
671,925
Database version 11g.
Execution Plan for the update:
Operation Object Name Rows Bytes Cost Object Node In/Out PStart PStop
UPDATE STATEMENT Optimizer Mode=ALL_ROWS 6 K 8120
UPDATE ODW_OWN2.ODS_CONTACTS_ADDR
HASH JOIN SEMI 6 K 256 K 8120
TABLE ACCESS FULL ODW_OWN2.ODS_CONTACTS_ADDR 6 K 203 K 7181
TABLE ACCESS FULL ODW_OWN2.ODS_IDL_EDGE_CONT_XREF 118 K 922 K 938
Edited by: user10566312 on May 14, 2012 1:07 AMThe code tag should be in lower case like this {noformat}{noformat}. Otherwise your code format will be lost.
Here is a update statementupdate ods_contacts_addr tgt
set (
best_times, odw_upd_by, odw_upd_dt, odw_upd_batch_id
) =
select best_time, odw_upd_by, odw_upd_dt, odw_upd_batch_id
from (
select listagg(tm, ' ') within group(order by con_addr_id) best_time,
'IDL - MASS MARKET' odw_upd_by,
sysdate odw_upd_dt,
'0' odw_upd_batch_id,
con_addr_id
from (
select Trim(Upper(con_addr_id)) con_addr_id,
||decode(Initcap(start_day), 'Monday', 'm', 'Tuesday', 'tu', 'Wednesday', 'w', 'Thursday', 'th', 'Friday', 'f', Initcap(start_day))
||'='
||trunc(((TO_DATE(start_tm,'HH12:MI:SS PM')-trunc(TO_DATE(start_tm,'HH12:MI:SS PM')))*24*60 ))
||','
||trunc(((TO_DATE(end_tm,'HH12:MI:SS PM')-trunc(TO_DATE(end_tm,'HH12:MI:SS PM')))*24*60)) tm
FROM (
select distinct * from ods_idl_edge_offc_bst_tm
WHERE con_addr_id is not null
group
by con_addr_id
where upper(tgt.edge_id) = con_addr_id
where exists
SELECT 1
FROM ods_idl_edge_cont_xref src
WHERE tgt.contacts_odw_id = src.contacts_odw_id
AND src.pc_flg='Y'
and exists
select null
from (
SELECT listagg(tm, ' ') WITHIN GROUP(ORDER BY con_addr_id) best_time,
'IDL - MASS MARKET' odw_upd_by,
SYSDATE odw_upd_dt,
'0' odw_upd_batch_id,
con_addr_id
FROM (
select Trim(Upper(con_addr_id)) con_addr_id,
||decode(Initcap(start_day), 'Monday', 'm', 'Tuesday', 'tu', 'Wednesday', 'w', 'Thursday', 'th', 'Friday', 'f', Initcap(start_day))
||'='
||trunc(((TO_DATE(start_tm,'HH12:MI:SS PM')-trunc(TO_DATE(start_tm,'HH12:MI:SS PM')))*24*60 ))
||','
||trunc(((TO_DATE(end_tm,'HH12:MI:SS PM')-trunc(TO_DATE(end_tm,'HH12:MI:SS PM')))*24*60)) tm
FROM (
SELECT DISTINCT * FROM ODS_IDL_EDGE_OFFC_BST_TM
WHERE con_addr_id is not null
GROUP
BY con_addr_id
where upper(tgt.edge_id) = con_addr_id
This is an untested code. If there is any syntax error then please fix it and try. -
SQL UPDATE statement in MS Excel
Hi All,
I have a request to perform a column update in ap_invoices_all table. There are around 1000 rows to be updated. The input is in the form of MS Excel.
Can somebody suggest how to make an update statement using MS Excel.
My query using excel should look like below:
UPDATE AP_INVOICES_ALL
SET description = '',
last_update_date = ,
last_updated_by =
WHERE org_id =
AND vendor_site_id =
AND invoice_num = ''
Regards,
Radhika.>
Can somebody suggest how to make an update statement using MS Excel.
>
as a way:
-- create heterogeneous service for ms excel
-- create dblink for this service
-- do update like
UPDATE AP_INVOICES_ALL
SET description = (
with t as
select value_for_description,
org_id,
vendor_site_id,
invoice_num
from sheet@dblink_to_excel
select t.value_for_description
from t t
where s.org_id = t.org_id
and s.vendor_site_id = t.vendor_site_id
and s.invoice_num = t.invoice_num
)other way:
-- create heterogeneous service for ms excel
-- create dblink for this service
-- insert for some temporary table
-- do update like above but based on temp table -
here are my columns:
SQL> desc leaguetable;
Name Null? Type
LEAGUETABLEID NOT NULL NUMBER(8)
TOURID NUMBER(8)
TEAMNAME VARCHAR2(25)
PLAYED NUMBER(3)
WON NUMBER(3)
LOST NUMBER(3)
DRAW NUMBER(3)
FORFOR NUMBER(3)
AGAINST NUMBER(3)
POINTS NUMBER(3)
POSITION NUMBER(3)
here is my update statement...
Update LEAGUETABLE set played = 1, won = 1, forfor = 3, against = -2, points = 3 where tourid = 10 AND teamName = dundee ;
here is my error...
ERROR at line 1:
ORA-00904: invalid column name
i dont see anything wrong with my sql statement. any ideas?You put us (me) on the wrong track... ORA-00904 is "ORA-00904 string: invalid identifier" not invalid column name.
But, there is your answer: value should be like "Dundee", with quotes.
Example:
SQL> desc leaguetable
Name Null? Type
LEAGUETABLEID NOT NULL NUMBER(8)
TOURID NUMBER(8)
TEAMNAME VARCHAR2(25)
PLAYED NUMBER(3)
WON NUMBER(3)
LOST NUMBER(3)
DRAW NUMBER(3)
FORFOR NUMBER(3)
AGAINST NUMBER(3)
POINTS NUMBER(3)
POSITION NUMBER(3)
SQL> Update LEAGUETABLE set played = 1, won = 1, forfor = 3, against = -2, points = 3 where tourid =
10 AND teamName = dundee ;
ERROR at line 1:
ORA-00904: "DUNDEE": invalid identifier
SQL> Update LEAGUETABLE set played = 1, won = 1, forfor = 3, against = -2, points = 3 where tourid =
10 and teamname = 'DUNDEE';
1 row updated. -
Native SQL Update statement error when more than one field used
Hi, I would make it simple. I update directly to a SQL server.
1-
When I update only one field works.
LOOP AT IT_MAT.
EXEC SQL.
UPDATE Articulos SET PrecioSinImp = :IT_MAT-PRECIOSINIMP WHERE Modelo = :IT_MAT-MODELO
ENDEXEC.
ENDLOOP.
This give me sy-subrc = 0
When I Try to update several fields doesnt works, any would can help me ?.
LOOP AT IT_MAT.
EXEC SQL.
UPDATE Articulos SET PrecioSinImp = :IT_MAT-PRECIOSINIMP
Descripcion = :IT_MAT-DESCRIPCION
WHERE Modelo = :IT_MAT-MODELO
ENDEXEC.
ENDLOOP.
This give me dump SQL error 170.
2- BTW, I have to leave this report program in a job so the data would be updated once a day in a job, so I have to update the existing data and add new one.
I Was thinking doing something like this.
LOOP AT it_table.
UPDATE DQL TABLE
IF sy-subrc <> 0.
INSERT DQL TABLE
ENDIF.
ENDLOOP.
This may works ??? because if this not work, I have to select single each one of the data in the SQL table, if it was founded UPDATE otherwise INSERT. And I dont like this aproach.
ThxHi Rodrigo,
I feel that your requirement is as below:
Depending on the criteria in the where clause, check whether the record exists or not.. If it does, then update the record with new values, else, create a new record..
You can do the same as below:
LOOP AT it_mat INTO e_mat. (e_mat of same structure as it_mat)
MOVE : xxx TO e_mat-yyy... and so on (Only change the non-key values)
MODIFY dbtable FROM e_mat.
ENDLOOP.
This code will create a new record if a record with the given key values in e_mat is not found, else, it will update the existing record with the new non-key values in the structure e_mat.
Thanks and Best Regards,
Vikas Bittera.
<b><REMOVED BY MODERATOR></b>
Message was edited by:
Alvaro Tejada Galindo -
Hi All,
I've a table with 5 columns, Col1, Col2, Col3, Col4 and Col5. The business requirement is that all the four columns Col1 through Col4 should be populated or none of the four columns should be populated.
Any row which doesnt satisfy the above rule should be marked as error.
I would like to know how do I update the Col5 with 'Error' when the above 2 rules doesnt satisfy using a direct update(sql) statement.
For Ex:
Col1 Col2 Col3 Col4 Col5
Row1 a b c d
Row2
Row3 a c Error
Row4 a b c Error
ThanksI'd probably create a function (I'll a
CREATE OR REPLACE FUNCTION num_null(
p_arg1 IN table_name.col1%type,
p_arg2 IN table_name.col2%type,
p_arg3 IN table_name.col3%type,
p_arg4 IN table_name.col4%type )
RETURN NUMBER
IS
l_num_null integer := 0;
BEGIN
IF( p_arg1 IS NULL )
THEN
l_num_null := l_num_null + 1;
END IF;
IF( p_arg2 IS NULL )
THEN
l_num_null := l_num_null + 1;
END IF;
IF( p_arg3 IS NULL )
THEN
l_num_null := l_num_null + 1;
END IF;
IF( p_arg4 IS NULL )
THEN
l_num_null := l_num_null + 1;
END IF;
RETURN l_num_null;
END;You could then do something like
UPDATE your_table
SET column5 = 'Error'
WHERE num_null( col1, col2, col3, col4 ) NOT IN( 0, 4 );It would be more efficient to do this entirely in SQL but the code would be more complex.
Justin
Maybe you are looking for
-
Hi, How do you create smart quotes in Photoshop? (Opening and close quotes) Thanks!
-
I am looking for a calendar app that lets me schedule like Outlook. For example, Meeting occurs on the 3rd Wed of every month, or event occurs every month on the 21st, or every weekday, etc. Also would like more options on notification timing than
-
MBP to TV using a cable - TV screen greys out after 10-15 mins
Hi there, I am looking for some assistance to solve the following issue that I cannot seem to resolve, I have my Macbook Pro (OS 10.8.5) hooked up to my 42' Philips TV (Model 42PFL560AH) using Belkin Mini DisplayPort to HDMI Cable. I then go to displ
-
FLEX Builder Pro 3 New Flex Project cannot configure J2EE
I have FLEX Builder Pro 3 installed on a Windows XP machine. LiveCycle Data Services is installed (with Tomcat) on a Linux RHEL 5 machine. When trying to create a new FLEX project and configuring a J2EE server am very confused on what to put in Roo
-
Hi Experts, Im trying to consume a Web Service. My client recently upgraded to Ecc 6 version, and want's now to change all teh used RFC's to Web Service, and for all i've red until now this step doesn't seems to be so hard, creating the wsdl from the