PLSQL Variables - sql

I'm new to programming and I was wonder how I would declare a variable I can use through out my code.
What I want to achieve is :
Myvariable = (select Column from table1 where column =1234 group by column);
select column from table2 where column in (myvariable);
select column from table3 where column in (myvariable);
and etc
Thanks in advance :)

If you're using PL/SQL Developer to access an Oracle database you can create a Test window (File - New - Test Window) with code similar to the following:
DECLARE
myVariable TABLE1.COLUMN%TYPE := 1234;
BEGIN
FOR aRow2 IN (SELECT COLUMN
FROM TABLE2
WHERE COLUMN = myVariable)
LOOP
DBMS_OUPUT.PUT_LINE('Do something with ''aRow2''');
END LOOP;
COMMIT;
FOR aRow3 IN (SELECT COLUMN
FROM TABLE3
WHERE COLUMN = myVariable)
LOOP
DBMS_OUPUT.PUT_LINE('Do something with ''aRow3''');
END LOOP;
COMMIT;
END;
You'll need to edit the above to do whatever you want with the rows from TABLE2 and TABLE3.
Best of luck.

this is not really a variable... you can write the sql like this
select column
from table2
where column in (select Column from table1 where column =1234 group by column);

You can use a temporary TEMPORARY TABLE bound to the current session:
DECLARE GLOBAL TEMPORARY TABLE temp
{
column INTEGER
}
ON COMMIT DELETE ROWS -- Specify PRESERVE ROWS if you want to keep them through commits
NOT LOGGED
ON ROLLBACK DELETE ROWS -- Remove this line if you want to keep rows when you rollback a transaction
You load the table:
insert into temp1 (select Column from table1 where column =1234 group by column)
Then you can use the data using generic code:
select column from table2 where column in (select column from temp1);
select column from table3 where column in (select column from temp1);

Related

Comparing :new value inserted with a trigger

I'm trying to build a trigger that checks if the row that is gonna be inserted, exists in another table.
Basically my 2 tables share one column, ID.
I want to prevent the insertion when the new row doesnt exist at least once in the other table.
I have this:
create or replace trigger BIM
before insert on TABLE1
for each row
begin
if not exists (select 1 from TABLE2 where TABLE2.ID = :new.TABLE1.ID)
then
raise_application_error(-20634, 'Error');
end if;
end;
But i'm getting this:
PLS-00049: bad bind variable 'NEW.TABLE1'
Gordon is right, It is preferable to use Foreign Key constraint for this scenario.
The problem with your code ( apart from the error which Gordon pointed out )is that unlike few other DBMS like Postgres, In Oracle you cannot use EXISTS in a PL/SQL expression/statements like IF. It should be a purely SQL statement.
create or replace trigger BIM
before insert on TABLE1
for each row
declare
l_id_exists INT;
begin
select CASE WHEN
exists (select 1 from TABLE2 where TABLE2.ID = :new.ID)
THEN 1
ELSE 0 END INTO l_id_exists from dual;
if l_id_exists = 0
then
raise_application_error(-20634, 'Error');
end if;
end;
/
DEMO
You don't need to repeat the table name:
create or replace trigger BIM
before insert on TABLE1
for each row
begin
if (select 1 from TABLE2 where TABLE2.ID = :new.ID and rownum = 0) is not null
then
raise_application_error(-20634, 'Error');
end if;
end;
That said, this is an odd requirement. I would recommend that you use a foreign key constraint, but you explicitly say "at least once". That leads me to suspect that you have a bad data model -- you are missing some sort of entity where the id would be the primary key of that table.

Nested SELECT statement in FROM clause

I want to get data from table which name is keeping in another table. Trying to get this as described below leads to getting result from nested SELECT only
select * from (select value from ex_scheme.ex_tab where name = 'ex_name.current_table_name')
I mean, I've got equivalent result as from just
select value from ex_scheme.ex_tab where name = 'ex_name.current_table_name'
query.
UPDATED
Ok, lets double-check if I was correctly understood.
I have to see one table data (lets call this table "table1"). I need to know this table name. And I know where its name is keeping. It is in another table (call it "names_table") in column "name" (row with column value = 'table1'). And I can get it by query
select name from names_table where value = 'table1'
If you know in advance the column and its type, you can build some dynamic SQL to dynamically query a table or another.
For example, say you have tables like the following:
create table table1(col) as (select 1 from dual);
create table table2(col) as (select 2 from dual);
create table tab_of_tabs (tab_name) as (select 'TABLE1' from dual);
You can use dynamic SQL to build a query that scans a table whose name is the result of a query:
SQL> declare
2 vSQL varchar2(1000);
3 vResult number;
4 begin
5 select 'select sum(col) from ' || tab_name -- build the query
6 into vSQL
7 from tab_of_tabs;
8 --
9 execute immediate vSQL into vResult; -- run the query
10 --
11 dbms_output.put_line('Result: ' || vResult);
12 end;
13 /
Result: 1
PL/SQL procedure successfully completed.
SQL>
If I understand correctly, you could use a nested query in a where clause. For example,
select * from table1 where table1.name in (select name from table2);
This assumes there's a column "name" in table1. The result of this query should return the rows in table1 that are in table2.
try giving alias
select n.* from (select value from ex_scheme.ex_tab where name = 'ex_name.current_table_name') n;
Update:
It is in another table (call it "names_table") in column "name" (row
with column value = 'table1').
this query will work
select n.* from (select name from ex_scheme.ex_tab where name = 'ex_name.current_table_name') n;
sub query fetches name of table from another table .

how to get table name from column value in oracle sql?

I have a main table that has two columns with table names and id's. And I have those tables with table names in my DB.
For example, I find particular table name, selecting id. And then I want to populate table with that name with data. And I want to do that in one query. How I can do that?
The goal: to populate with data all tables at once, that has the names that similar with values in table name column from main table.
That is how I'm getting the list of tables. I should probably loop through it.
select tbl from asp_tbl where asp in (
select id from (
SELECT * FROM DIMENSION WHERE EXTERNALKEY LIKE 'W16%')
);
And then I will try to merge the data from other tables inside the table that needs to be populated:
MERGE INTO tbl d
USING
(SELECT ? nums, ? names from data_table) s
ON(d.product = s.product and d.ga = s.ga and d.metric_id = s.metric_id)
WHEN MATCHED THEN UPDATE SET d.names = s.names
WHEN NOT MATCHED THEN INSERT (nums, names)values(s.nums,s.names);
Did I provide enough info?
As I understand you need some stored procedure witch may fulfil a table with some test data. If so you may write something like:
create procedure fulfil_test_data (p_table_name varchar2) is
begin
for x IN (select tbl from asp_tbl where asp in (
SELECT table_id FROM DIMENSION WHERE EXTERNALKEY LIKE p_table_name )) loop
execute immediate 'insert into '|| x.tbl ||' (nums, names)
select level , chr(ascci(''A'') + mod(level,26)) from dual connect by level < 1001';
end loop;
end;
/
And call it
begin
fulfil_test_data('W16%');
end;
/

Looping in PL/SQL

Basically I want to select data from a table based on id's of another table. So the algorithm goes:
foreach i in (select distinct id from table1)
{
select * from table2 where table2.id=i;
}
How to perform this function with an SQL query? I understand that we could use joins etc instead of looping, however, my requirement is such that I need to pass id's one by one in a for-loop only.
select * from table2 where table2.id IN (select distinct id from table1)
Use for instead of foreach.
Place PL/SQL into a begin .... end; block (but see the declare below)
The =i should read =i.id as i is the complete record from the select statement, but you're only interested in its id field.
In PL/SQL, a select statement must be fetched into a variable. Therefore, you have to declare an according variable: r table1%rowtype
The declaration of such variables is in the declare ... section of PL/SQL blocks.
The "algorithm" then becomes
declare
r table2%rowtype;
begin
for i in (select distinct id from table1) loop
select * into r from table2 where table2.id = i.id;
end loop;
end;

selecting multiple rows into single variable and to use it in where clause of another delete query

As we can select multiple rows into single variable declared as some_table.rowtype in SQL. In the same way I want to fetch multiple row values of single column into a variable. So,
How can I declare it's variable type?
Can I use that in where clause?
Can I iterate through that variable(collection) values?
I want to do it in a stored procedure to delete one or more table records matching that variable values.
Does this work for you?
DELETE FROM myTable
WHERE myTable.ID IN
(SELECT ID
FROM myOtherTable
WHERE myOtherCondition)
CREATE TYPE number_table AS TABLE OF NUMBER;
/
DECLARE
my_number_table number_table;
BEGIN
SELECT some_column BULK COLLECT INTO my_number_table FROM some_table;
DELETE FROM some_other_table WHERE some_column IN (
SELECT column_value FROM TABLE(CAST(my_number_table AS number_table))
);
END;
/