i am fairly new to the Oracle DBMS and would like to know how to use a member of a nested table in a where clause
specifically
i have a nested table named poll_nest
SQL> desc poll_nest
Name Null? Type
----------------------------------------- -------- ----------------------------
ID VARCHAR2(20)
CID VARCHAR2(20)
which was created as follows
create or replace type voter_arrive as object(id varchar(20),cid varchar(20));
create or replace type poller as table of voter_arrive;
and then it was inserted into the election table as poll_nest
SQL> desc election;
Name Null? Type
----------------------------------------- -------- ----------------------------
REGION VARCHAR2(20)
STIME TIMESTAMP(6)
ETIME TIMESTAMP(6)
VOTES POLLER
i need to take some actions based on the value of the cid attribute of poll_nest that is currently entered(like incrementing a value based on the cid)
so i used an after trigger in which i did this:
select distinct t.cid into voted from election e,table(e.votes) t where t.cid=:new.votes.cid;
but i get a compilation error.
i saw this answer and this too:
Oracle Nested Table predicate in where clause
but couldn't understand how they work..
could someone please help me with the syntax?
poll_nest is not a nested table. Its table that stores PL SQL object.
From http://www.orafaq.com/wiki/NESTED_TABLE :
NESTED TABLE is an Oracle data type used to support columns containing multivalued attributes, in this case, columns that can hold an entire sub-table.
You can insert value in table of object type by first instantiating object constructor like
insert into poll_nest values (voter_arrive('122','112'));
For accessing the inserted value you can use
select e.voter.arrive.cid from poll_tab e where e.voter_arrive.id = '122';
check out this link too: http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/objects.htm
Update:
I looked up oracle documentation http://docs.oracle.com/cd/A97630_01/appdev.920/a96624/05_colls.htm , and I found that poller is a nested table. I don't know why they call it nested table, it should be called PL/SQL table only.
I assumed poll_nest to be like, and answered the question
CREATE TABLE APPS.POLL_NEST
(
VOTER APPS.VOTER_ARRIVE
)
but now I think you have created table and objects like
create or replace type voter_arrive as object(id varchar(20),cid varchar(20));
create or replace type poller as table of voter_arrive;
create table election(
REGION VARCHAR2(20),
STIME TIMESTAMP(6),
ETIME TIMESTAMP(6),
VOTES POLLER
) NESTED TABLE VOTES STORE AS VOTES_TAB;
For each region(which should be unique), you are going to save records in VOTES nested table .if I am correct
INSERT INTO election
VALUES ( 'A',
CURRENT_TIMESTAMP,
CURRENT_TIMESTAMP,poller(voter_arrive('100','001'),voter_arrive('200','002')) )
poller() is a constructor of nested table type poller. All values passed to constructor will create new row in poller. So, you can perform insert and update in election table like
INSERT INTO table (select e.votes from election e where region ='A') values((voter_arrive('300','003')))
To access individual row in poller nested table you need to use TABLE() function like this:
select * from table (select e.votes from election e where region ='A') a where a.id = 100
Related
I have 4 tables:
Table A:
LogID (unique identifier),
UserID (bigint),
LogDate (date/time),
LogEventID (int),
IPID (varchar(36)),
UserAgentID (varchar(36))
Table B:
IPID (unique identifier),
IPAddress (varchar(255))
Table C:
UserAgentID (unique identifier),
UserAgent (varchar(255))
Table D:
LogEventID (int),
LogEvent (varchar(255))
I am trying to write the to Table A but need to check Table B, Table C and Table D contain data so I can link them. If they don’t contain any data, I would need to create some. Some of the tables may contain data, sometimes none of them may.
Pretty much everything, really struggling
first, you do a insert into table B, C, D WHERE NOT EXISTS
example
INSERT INTO TableB (IPID, IPAddress)
SELECT #IPPD, #IPAddress
WHERE NOT EXISTS
(
SELECT *
FROM TableB x
WHERE x.IPID = #IPID
)
then you insert into table A
INSERT INTO TableA ( . . . )
SELECT . . .
SQL Server doesn't let you modify multiple tables in a single statement, so you cannot do this with a single statement.
What can you do?
You can wrap the multiple statements in a single transaction, if your goal is to modify the database only once.
You can write the multiple statements in stored procedure.
What you really probably want is a view with insert triggers on the view. You can define a view that is the join of the tables with the values from the reference tables. An insert trigger can then check if the values exist and replace them with the appropriate ids. Or, insert into the appropriate table.
The third option does exactly what you want. I find that it is a bit of trouble to maintain triggers, so for an application, I would prefer wrapping the logic in a stored procedure.
I'm in trouble with the implementation of a trigger.
Assuming that I have two types:
CREATE TYPE customer_t AS OBJECT(
code INTEGER,
name VARCHAR(20),
surname VARCHAR(20),
age INTEGER);
and the type
CREATE TYPE ticket_t AS OBJECT (
price INTEGER,
cust REF customer_t
)
And then I have the associate tables:
CREATE TABLE customers OF TYPE customer_t
CREATE TABLE tickets OF TYPE ticket_t
I have to do an exercise so I have to create a trigger for ensure that a customer won't buy more than 10 tickets but, if I use command like "select count(*)" I get an error because I can't access to mutating table.
Please can anyone help me with this trigger?
EDIT:
I populated the tables as follows:
INSERT INTO custs (code, name, surname, age) values (123, 'Paolo', 'Past', 32);
and repeating the following operation ten times:
INSERT INTO tickets (price, cust) values
(4, (SELECT * FROM (SELECT REF(T) FROM custs T WHERE name = 'Paolo' AND surname = 'Past') WHERE rownum < 2))
The trigger implemented is:
create or replace
trigger check_num_ticket after insert on tickets
for each row
declare
num_ticket number;
begin
SELECT count(*) INTO num_ticket FROM tickets WHERE :new.cust = cust;
if (num_ticket >= 10) then
raise_application_error('-20099', 'no ticket available');
end if;
end;
And I get this error:
A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
You are getting the mutating table error, because you are inserting in the same table where you want to get the row count for. Imagine your insert statement inserts two rows. There is no rule which row to insert first and which last, but your trigger fires on one inserted row and wants to know how many rows are already in the table. The DBMS tells you this is undefined, as the table is currently mutating.
You need an after statement trigger instead of a before row trigger. So when the insert statement's inserts are done, you look at the table to see whether there are suddenly customers with too many rows in it.
(A great alternative is a compound trigger. It combines row and statement triggers. So in the after row section you'd remember the customers in some array/collection and in the after statement section you'd look up the table for only the remembered customers.)
I am curious if I could use the type of an existing table's column when I create another column. Just as using a data type like varchar, I would like to have my column the same type as a column in another table.
I am imagining something like
CREATE TABLE FIRST (id NUMBER(5), name VARCHAR(25))
and then
CREATE TABLE SECOND (id NUMBER(6), value FIRST.NAME%TYPE)
and the type of the VALUE column would be VARCHAR(25)
I see this as a generic SQL question, though I am using Oracle.
You can do the following:
CREATE TABLE SECOND AS (
SELECT ID, NAME AS VALUE
FROM FIRST
WHERE 1 = 2
);
If think the %type syntax is a plsql thing only
In standard SQL, you'd write a CREATE DOMAIN statement.
CREATE DOMAIN my_name_type VARCHAR(25);
But I don't think Oracle supports CREATE DOMAIN, so you I think you need to create an object instead.
create type my_name_type as object
( my_name_col varchar2(25));
In either case, you'd use it directly in creating a table.
create table test (
user_name my_name_type
);
I recall that the syntax for INSERT statements is a little weird; check the docs for that.
You could do this in SQL Server by using SELECT INTO:
SELECT TOP 0 CAST(0 as int) as 'id', Field
INTO NewTable
FROM OtherTable
I have created an object type(address-city,state) in Oracle 10g .Then table cust_contact contains field of type address.Can anyone please provide SQL query to insert and retrieve values from this table including the type?
Selection is easy. Just include the type column in the query projection. Assuming that the ADDRESS column is called contact_address:
select id, contact_name, contact_address
from cust_contact
/
With inserts you need to specify the type in the statement:
insert into cust_contact values
(some_seq.nextval
, 'MR KNOX'
, address(34, 'Main Street', 'Whoville', 'SU')
)
/
You can also use the "." syntax when retrieving columns:
select c.contact_address.city from cust_contact c;
Please note that if cust_contact is a table of objects, then you must use the table alias "c".
for example :
first create type object say as address ,for this synatx or query is used:
create type address_ty as object(Street varchar2(50),City char(10),Zip number(6));
now use this address_ty as datatype in the time of table creation
for example:
create table Example(emp_name varchar2(10),emp_id number(10),address address_ty);
this will create table Example having
Address as address_ty as a datatype..
Now insert into Values In Example Table
Insert Into example Values('Sandeep Kumar',595,address_ty('Snap on sector 126','Noida',201301);
tHANX....
Is it possible to create a table which has a check constraint on one of the column whose value lies within the result set given by another sql query
eg.
create table tablename
(
name varchar(10),
rollno int
)check rollno in (select rollno from anotherDatabase.TableName,candidateRoll)
or any thing like that.
I dont have to use it anywhere but still want to know.
If you can't achieve what you want with a foreign key reference, so you can if you wrap the SELECT statement in a function call.
Your check constraint expression may look something like:
(dbo.SomeFunction([col1]) != 0)
The function might look like this (assuming the column is a varchar):
create function dbo.SomeFunction(#arg varchar(max))
returns bit
as
begin
return
(
select count(*) from SomeOthertable where col2 = #arg
)
end
EDIT (2010/06/9): Regarding Anthony's comment, my testing has shown that a count(*) value of greater than 1 is still returned as 1. So it would seem that the function is okay, even though it should probably explicitly return 1 or 0. Or, if you are interested in the actual rowcount, change the return type from BIT to INT.
Yes: foreign key for same database links
create table tablename
(
name varchar(10),
rollno int FOREIGN KEY (candidateRoll) REFERENCES OtherTableName (candidateRoll)
)
If it's a different database then use code e.g. insert via stored proc or enforce via a trigger