I need some help with creating a select statement that will use a ref.
I managed to insert the values fine but when i try to extract the values with a where statement the output is either that the datatype is wrong or it will output the two tables and the data they both contain.
this is just an example:
Create or replace table1_Type as object {
id integer,
dateStart date,
etc varchar2(20));
}
/
create table table1 of table1_type;
Create or replace table2_type as object
id integer,
items varchar2(30),
datePurchased varchar2(20),
table1_Ref REF table1_type);
/
create table table2 of table2_type;
so i tried
Select * from table2 a, table1 b where table1.id = table2.table1_ref
Select * from table2 a, table1 b where table1.id = deref(b.table1_ref)
which does not work.
Iam new to this so sorry if i didnt explain properly. What i am trying to do is to select the items for example that were purchased by table1/id so the output should only display
the items that were purchased by a certain id.
Create or replace type table1_Type as object (
id integer,
dateStart date,
etc varchar2(20));
-- TYPE TABLE1_TYPE compiled
create table table1 of table1_type;
-- table TABLE1 created.
Create or replace type table2_type as object(
id integer,
items varchar2(30),
datePurchased varchar2(20),
table1_Ref REF table1_type);
-- TYPE TABLE2_TYPE compiled
create table table2 of table2_type;
--table TABLE2 created.
INSERT INTO table1 VALUES(table1_Type(1, SYSDATE, 'etc1...'));
INSERT INTO table1 VALUES(table1_Type(2, SYSDATE, 'etc2...'));
SELECT REF(t)
FROM table1 t
WHERE id = 1;
-- [TST.TABLE1_TYPE]
DECLARE
l_table_1_id_1 REF table1_Type;
l_table_1_id_2 REF table1_Type;
BEGIN
SELECT REF(t)
INTO l_table_1_id_1
FROM table1 t
WHERE id = 1;
SELECT REF(t)
INTO l_table_1_id_2
FROM table1 t
WHERE id = 2;
INSERT INTO table2 VALUES (21, 'item21', SYSDATE, l_table_1_id_1);
INSERT INTO table2 VALUES (22, 'item22', SYSDATE, l_table_1_id_2);
END;
-- anonymous block completed
SELECT COUNT(*) FROM table1;
-- 2
SELECT COUNT(*) FROM table2;
-- 2
SELECT * FROM table1;
/*
1 2013-06-16 03:51:50 etc1...
2 2013-06-16 03:52:05 etc2...
*/
SELECT * FROM table2;
/*
21 item21 2013-06-16 04:06:26 [TST.TABLE1_TYPE]
22 item22 2013-06-16 04:06:26 [TST.TABLE1_TYPE]
*/
SELECT *
FROM table1 t1
JOIN table2 t2
ON REF(t1) = t2.table1_Ref;
/*
1 2013-06-16 03:51:50 etc1... 21 item21 2013-06-16 04:06:26 [TST.TABLE1_TYPE]
2 2013-06-16 03:52:05 etc2... 22 item22 2013-06-16 04:06:26 [TST.TABLE1_TYPE]
*/
Related
If customer id exists in table A, insert order in table B.
if customer id does not exist in table A, insert customer id in table A and then order in table B.
I have been trying to achieve this with if/else and merge but keep running into
invalid sql statement.
IF EXISTS (SELECT CustomerID FROM Customer_T WHERE CustomerID = 18)
Insert into Order_T
values(79,18,to_date('09/28/2021','mm/dd/yyyy'),to_date('10/01/2021','mm/dd/yyyy'),1,3)
ELSE
insert INTO Customer_T VALUES (18,'Capitol Industries Ltd', '999 Fifth Avenue', 'New York', 'NY','10015')
insert into Order_T values (79,18,to_date('09/28/2021','mm/dd/yyyy'),to_date('10/01/2021','mm/dd/yyyy'),1,3)
END IF;
The IF THEN ELSE logic is not needed for this case. Instead make use of the database built-in functionality. customerid should be your primary key, so if you try to insert and it already exists that will raise the DUP_VAL_ON_INDEX exception.
Check the following example:
-- create tables
create table customers (
id number generated by default on null as identity
constraint customers_id_pk primary key,
name varchar2(255 char)
)
;
create table orders (
id number generated by default on null as identity
constraint orders_id_pk primary key,
customer_id number
constraint orders_customer_id_fk
references customers on delete cascade,
product varchar2(100 char)
)
;
BEGIN
BEGIN
insert INTO customers VALUES (2,'Capitol Industries Ltd');
EXCEPTION WHEN DUP_VAL_ON_INDEX THEN
NULL;
END;
insert into orders (customer_id,product) values (2,'a book');
END;
/
run the above block a couple of times. Only the first time it will insert a customer.
Suppose you have 2 very simple tables.
Tables
create table T1( num_ )
as
select 1 from dual ;
create table T2( num_ )
as
select 200 from dual ;
An anonymous block, containing IF .. ELSE .. END IF and EXISTS() similar to the code in your question, causes an error:
function or pseudo-column 'EXISTS' may be used inside a SQL statement
only
begin
if exists( select num_ from T1 where num_ = 2 ) then
insert into T2( num_ ) values( 2 ) ;
dbms_output.put_line( 'if' ) ;
else
insert into T1( num_ ) values( 2 ) ;
insert into T2( num_ ) values( 2 ) ;
dbms_output.put_line( 'else' ) ;
end if ;
end ;
/
-- error:
... function or pseudo-column 'EXISTS' may be used inside a SQL statement only
One solution may be to do the following (see asktom.oracle.com - Equivalent for EXISTS() in an IF statement)
begin
for x in ( select count(*) cnt
from dual
where exists ( select num_ from T1 where num_ = 2 )
) loop
if ( x.cnt = 1 ) then -- found
insert into T2( num_ ) values( 2 ) ;
dbms_output.put_line( 'if' ) ;
else -- not found
insert into T1( num_ ) values( 2 ) ;
insert into T2( num_ ) values( 2 ) ;
dbms_output.put_line( 'else' ) ;
end if;
end loop;
end;
/
-- output:
1 rows affected
dbms_output:
else
After the first execution of the anonymous block, the tables contain the following rows:
select num_, '<- T1' as table_ from T1
union all
select num_, '<- T2' from T2 ;
-- result
NUM_ TABLE_
1 <- T1
2 <- T1
200 <- T2
2 <- T2
Execute the anonymous block again, and you get ...
1 rows affected
dbms_output:
if
-- tables
NUM_ TABLE_
1 <- T1
2 <- T1
200 <- T2
2 <- T2
2 <- T2
DBfiddle here.
You may use multitable insert and use the fact that aggregate function without group by always returns a row with null in case of absent (= not satisfying where condition) row.
The code is below:
insert into customers(id, name, company, state)
values (1, 'Some name', 'Some company', 'NY')
1 rows affected
insert all
when cust_exists = 0
then
into customers (id, name, company, state)
values (cust_id, cust_name, company, state)
when 1 = 1
then
into orders (id, customer_id, order_date, due_date, some_id)
values(order_id, cust_id, order_date, due_date, some_id)
select
1 as order_id,
1 as cust_id,
'Some other name' as cust_name,
'Company' as company,
'NY' as state,
date '2021-09-28' as order_date,
date '2021-10-03' as due_date,
100 as some_id,
nvl(max(1), 0) as cust_exists
from customers
where id = 1
1 rows affected
insert all
when cust_exists = 0
then
into customers (id, name, company, state)
values (cust_id, cust_name, company, state)
when 1 = 1
then
into orders (id, customer_id, order_date, due_date, some_id)
values(order_id, cust_id, order_date, due_date, some_id)
select
2 as order_id,
2 as cust_id,
'Some other name' as cust_name,
'Company' as company,
'NY' as state,
date '2021-09-28' as order_date,
date '2021-10-03' as due_date,
100 as some_id,
nvl(max(1), 0) as cust_exists
from customers
where id = 2
2 rows affected
You may also use two inserts with documented ignore_row_on_dupkey_index hint, which does what its name implies.
insert /*+
ignore_row_on_dupkey_index(customers(id))
*/
into customers (id, name, company, state)
values (2, 'Name', 'Comp', 'NY')
✓
insert into orders (id, customer_id, order_date, due_date, some_id)
values (3, 2, date '2021-09-30', date '2021-10-07', 5)
1 rows affected
select *
from customers
ID
NAME
COMPANY
STATE
1
Some name
Some company
NY
2
Some other name
Company
NY
db<>fiddle here
table 1
id pk1 timestamp
1 a 10-jul-2019
2 h 11-mar-2019
3 k 19-jul-2019
4 j 7-n0v-2018
5 h 11-jul-2019
table 2
col start_date end_date
a 10-jul-2019
h 11-mar-2019 11-jul-2019
k 19-jul-2019
j 7-nov-2018
h 11-jul-2019
Q:> I want this process to be repeat after equal interval of time.
if a new value got enter into the table 1 then same value should enter into the table 2 but if existing values enters in table 1 then just update end date of previous same value of table 2 and add one new value with null end date into table 2 (example value H in table 1 and table 2).
we need to use only single query.
with merge we are not able to get this
if a new value got enter into the table 1 then same value should enter
into the table 2 but if existing values enters in table 1 then just
update end date of previous same value of table 2 and add one new
value with null end date into table 2
Your scenario need a Trigger to be created on Table1. You can put down your logic to update Table2 in the Trigger.
See below demo:
--Table1 DDL
Create table tab1 (
id number,
pk1 varchar(1),
time_stamp date
);
--Table2 DDL
create table tab2 (
col varchar(1),
start_date date,
end_date date
);
Here is Trigger on Table1
Create or replace trigger t1
before insert on tab1
for each row
begin
DECLARE
l_exists INTEGER;
BEGIN
SELECT COUNT(*)
INTO l_exists
FROM tab2
WHERE col = :new.pk1 ;
IF l_exists = 0
THEN
INSERT INTO TAB2
values
(:new.pk1,:new.time_stamp,null);
ELSE
Update tab2
set end_date = :new.time_stamp
where col = :new.pk1;
INSERT INTO TAB2
values
(:new.pk1,:new.time_stamp,null);
END IF;
END;
end;
--Execution:
insert into tab1 values (1,'a',to_date('10-jul-2019','DD-MON-YYYY'));
insert into tab1 values (2,'h',to_date('11-mar-2019','DD-MON-YYYY'));
insert into tab1 values (3,'k',to_date('19-jul-2019','DD-MON-YYYY'));
insert into tab1 values (4,'j',to_date('07-nov-2019','DD-MON-YYYY'));
insert into tab1 values (5,'h',to_date('11-jul-2019','DD-MON-YYYY'));
Commit;
SQL> select * from tab1;
ID P TIME_STAM
---------- - ---------
1 a 10-JUL-19
3 k 19-JUL-19
4 j 07-NOV-19
2 h 11-MAR-19
5 h 11-JUL-19
SQL> select * from tab2;
C START_DAT END_DATE
- --------- ---------
a 10-JUL-19
k 19-JUL-19
j 07-NOV-19
h 11-MAR-19 11-JUL-19
h 11-JUL-19
I'm trying to compare a global temporary table to another table and want to insert into a log table but can not seem to find the best/most efficient way to accomplish this.
Log Table
CREATE TABLE LogTable
(
Date_Time DATETIME,
Name VARCHAR2(10 CHAR),
old VARCHAR2(20 CHAR),
new VARCHAR2(20 CHAR),
)
Object Type
CREATE OR REPLACE type dbo.P_REC AS OBJECT
(
ATTR1 VARCHAR2(10 CHAR),
ATTR2 VARCHAR2(20 CHAR),
ATTR3 VARCHAR2(20 CHAR),
ATTR4 VARCHAR2(20 CHAR)
);
Collection Type
CREATE OR REPLACE type dbo.P_REC_LIST IS TABLE OF P_REC;
Stored Procedure
PROCEDURE PASSPEOPLETOORACLE(tmpCollection IN P_REC_LIST , resultCursor out sys_refcursor)
IS
BEGIN
IF tmpCollection .count > 0 THEN
INSERT INTO tmpPTbl SELECT * FROM table1; <--tmpPTbl is a copy of table1 before the merge statement.
MERGE INTO table1 MKTP
USING (
WITH tmpTBL AS
(
SELECT ADCOLL.ATTR1,
ADCOLL.ATTR2,
MV.ATTR3,
MV.ATTR4
FROM TABLE(tmpCollection) ADCOLL
LEFT JOIN materializedView MV
ON ADCOLL.ATTR1 = MV.ATTR1
)
SELECT DISTINCT COALESCE(tmpTBL.ATTR1,MKtmpTBL.ATTR1) AS ATTR1,
tmpTBL.ATTR2,
tmpTBL.ATTR3,
tmpTBL.ATTR4,
CASE WHEN tmpTBL.ATTR1 IS NULL
THEN 'Y' ELSE 'N' END
match_flag FROM tmpTBL
FULL JOIN table1 MKtmpTBL
ON MKtmpTBL.ATTR1 = tmpTBL.ATTR1
) usingTBL
ON (MKTP.ATTR1 = usingTBL.ATTR1)
WHEN MATCHED THEN
UPDATE SET MKTP.ATTR2 = usingTBL.ATTR2,
MKTP.ATTR3 = usingTBL.ATTR3,
MKTP.ATTR4 = usingTBL.ATTR4,
DELETE WHERE match_flag = 'Y'
WHEN NOT MATCHED THEN
INSERT (ATTR1)
VALUES (usingTBL.ATTR1);
END IF;
END;
Id like a way to compare the newly update records in table1 to the prior records in tmpPTbl and where the old and new values differ, insert a new row into the log table.
2019-02-14 23:59:59,jdoe,abcd,efgh would be an example of a record inserted into the log table.
tmpPTbl & table1 both have 50 columns in them & about 16k rows on average.
The best solution for you would be to create a Trigger on table Table1. So that any operation occurs on Table1 it can be logged to Logtable. See below demo:
CREATE TABLE table1
(col1 VARCHAR2(10),
col2 VARCHAR2(10),
col3 VARCHAR2(10) );
/
--Trigger
CREATE OR REPLACE TRIGGER Log_Entry before
INSERT OR
UPDATE ON table1 FOR EACH row
BEGIN
IF INSERTING THEN
INSERT INTO LogTable VALUES
(sysdate, :new.col1, :new.col2, :new.col3
);
ELSIF UPDATING THEN
INSERT INTO LogTable VALUES
(sysdate, :old.col1, :old.col2, :old.col3
);
END IF;
END;
/
Execution:
SQL> Insert into table1 values ('A','B','C');
SQL>Update table1
set col1 ='Z'
where col1 = 'A';
SQL> Merge INTO table1 tb1 USING
(SELECT 'Z' col1 , 'D' col2, 'K' col3 FROM dual
) tb2 ON (tb1.col1 = tb2.col1)
WHEN matched THEN
UPDATE SET tb1.col2=tb2.col2 WHEN NOT matched THEN
INSERT VALUES
(tb2.col1,tb2.col2,tb2.col3
);
SQL>Commit;
SQL> Select * from logtable;
DATE_TIME NAME OLD NEW
--------- ---------- -------------------- --------------------
15-FEB-19 A B C
15-FEB-19 Z B C
15-FEB-19 Z B C
Note there is no need to copy data to tmpPTbl table as well.
I want to connect query to connect 1st table 1st row and 2nd table first two column
means,
Table A,
ID Date Username Password
1 19/2/2016 XYZ ******
2 19/2/2016 ABC ******
Table B,
ID Date Username City
1 19/2/2016 XYZ NYC
2 19/2/2016 ABC LA
that when I insert some data in table A's 1st row then i want to check that data is available at table B's ID,DATE
Do you mean you want to enforce referential integrity between this two tables?
In this case you need a foreign key constraint
ALTER TABLE table_a
ADD CONSTRAINT reference_table_b_fk
FOREIGN KEY (id, date)
REFERENCES table_b (id, date);
If you want to just check before performing Insert option try this:
IF EXISTS (SELECT ID FROM TableB WHERE ID=1 AND Date='19/2/2016')
// Your either insert or not query
ELSE
// Your else logic will be here
so if you insert an entry into table1 only if an equivalent entry exists in table2, here's a little script to do that:
create table table1 (id number(2), date_t1 date, username varchar2(5), password varchar2(8));
create table table2 (id number(2), date_t1 date, username varchar2(5), city varchar2(8));
insert into table1 values (1, to_date('16.02.2016', 'dd.mm.yyyy'), 'XYZ', 'ABC123');
insert into table1 values (2, to_date('16.02.2016', 'dd.mm.yyyy'), 'ABC', 'XYZ123');
insert into table2 values (1, to_date('16.02.2016', 'dd.mm.yyyy'), 'XYZ', 'NYC');
insert into table2 values (2, to_date('16.02.2016', 'dd.mm.yyyy'), 'ABC', 'LA');
declare
n_id number(2);
d_date date;
v_username varchar2(5);
v_password varchar2(8);
n_check number(1);
begin
n_check := 0;
-- fill the variables with data which you want to insert:
n_id := 2;
d_date := to_date('16.02.2016', 'dd.mm.yyyy');
v_username := 'ABC';
v_password := 'CCCCC';
-- check whether an entry exists in table2:
begin
select count(1)
into n_check
from table2 t2
where t2.id = n_id
and trunc(t2.date_t1) = trunc(d_date);
exception when no_data_found then n_check := 0;
end;
-- if an entry exists in table2, then insert into table1:
if n_check <> 0 then
insert into table1 (id, date_t1, username, password)
values (n_id, d_date, v_username, v_password);
end if;
end;
/
select * from table1;
select * from table2;
delete from table1;
delete from table2;
I would like to insert data into a table based on all the values of a secondary table's column. For example
I have two tables
CREATE TABLE Table1 (
id int identity(1, 1) not null,
FullName varchar(100),
Age int,
CourseID int
)
CREATE TABLE Table2 (
id int identity(1, 1) not null,
Courses int
)
I would like to perform something like this ..
insert into Table1 ('Auser',20,'And the list of Courses that I get from Table2')
Is there a way I can do this in sql server ?
So for one new user you want to insert all available courses?
INSERT INTO Table1
SELECT 'Ausser', 20, t2.Courses
FROM Table2 t2;
Edit: Here's the fiddle: http://sqlfiddle.com/#!3/89470/1/0
Since, you are using SQL Server 2008, you can use the MERGE STATEMENT . Here is a program for your example
CREATE TABLE Table1
(
Id int identity(1, 1) not null,
FullName varchar(100),
Age int,
CourseID int
)
CREATE TABLE Table2
(
ID int identity(1, 1) not null,
Courses int
);
INSERT INTO Table2
SELECT 10 UNION ALL SELECT 20 UNION ALL
SELECT 30 UNION ALL SELECT 40 UNION ALL SELECT 50;
--The Merge Query
MERGE Table1 AS t1
USING (SELECT * FROM Table2) AS t2
ON t1.CourseID= t2.Courses
WHEN NOT MATCHED THEN
INSERT(FullName,Age,CourseID)
VALUES('Ausser',20,t2.Courses);
SELECT *
FROM Table1
DROP TABLE Table1
DROP TABLE Table2
//Result
Id FullName Age CourseID
1 Ausser 20 10
2 Ausser 20 20
3 Ausser 20 30
4 Ausser 20 40
5 Ausser 20 50