Declaring a Temporary Variable in Oracle Database - sql

i have worked previously with SQL Server and was able to learn how to create temporary variables and use them in SQL
i used to write something like this:
declare #Student nvarchar(255)
select #Student = studentname from sometable where somecondition = 1
declare #teacher nvarchar(255)
select #teacher = teachername from sometable2 where somecondition >2
and then
select #student, #teacher, other columns from sometable where some condition
i want to do the same thing in ORACLE Database.
Please Help!

If you want to do this in SQL*Plus without using PL/SQL, you can use substitution variables:
column studentname new_value l_studentname
select studentname from sometable where somecondition = 1;
column teachername new_value l_teachername
select teachername from sometable2 where somecondition >2;
select '&l_studentname', '&l_teachername,' other columns
from sometable where somecondition;
The new_value clause in the column directive automatically assigns the value from any following select to a local variable, which I've prepended with l_ but you can call anything. You then reference that local variable in future queries with the & variable substitution syntax.
You can use them pretty much anywhere you'd normally have a value. e.g. in the where clause. Note that text values have to be enclosed in quotes, hence '&l_studentname'; without the quotes the value would be interpreted as a column name in this case, which wouldn't work.

You can declare a variable say
SOME_VAR VARCHAR2(255);
Then use it in your query directly
SELECT DISTINCT YT.TEACHER_NAME
INTO SOME_VAR
FROM YOUR_TABLE YT
WHERE YT.TEACHER_ID = 1;
Then you are free to use this variable, SOME_VAR, for further use
Of course, this will not work in a simple SQL statement, but in case you use it in a programming block, like a procedure.
Hope it helps

Related

Anything like template literals while writing a search query in SQL?

I am writing a stored procedure to get a particular value.
declare #num int
set #num = (SELECT Id
FROM [sometable]
WHERE Name like '%today%')
-- returns #num = 1
Select Value
FROM [anothertable]
where name like 'days1'
In the last line of the query I want to add "1" or any other number after 'days', depending on the variable #num.
How can I do it, sort of like how we use template literals in Javascript, using the ${} syntax but in SQL?
You can just use the first query as a sub-query of the second:
select [Value]
from anothertable
where [name] = Concat('days', (select Id from sometable where [Name] like '%today%'));

SQL AS statement without column name shortcut

what does the AS in a statement such as below do?
SELECT column AS
FROM table
Since there is no shortcut, does it even do anything?
You did not tag your actual RDBMS, the following is valid for SQL-Server, but you'll be able to transfer this to your system:
--A dummy table as declared table variable
DECLARE #DummyTbl TABLE(SomeColumn INT);
INSERT INTO #DummyTbl VALUES(1),(2),(3);
--Variation of namings
SELECT SomeColumn --The orginal name
,SomeColumn AS OtherName --A classical alias
,SomeColumn test --The alias does NOT need the 'AS'
,SomeColumn [AS] --You may name your output 'AS'
FROM #DummyTbl;
But your syntax is - at least with SQL Server - not valid. AS is - in this context - a reserved word.

Using a string of quoted values in a variable for a SQL WHERE CLAUSE

The answer escapes me...maybe because it is not possible...
Example that works...
SELECT * FROM TABLEA WHERE FIELD1 IN ('aaa','bbb','ccc')
Example that does not work...
Attempt to leverage variable so that I can define the values once in a string of statements
DECLARE #ListValues VARCHAR(50)
SET #ListValues = '''aaa'',''bbb'',''ccc'''
SELECT * FROM TABLEA WHERE FIELD1 IN (#ListValues)
This is is obviously only a small part of the equation and for other reasons...
I cannot leverage a table for the values and change this to a true sub-query
The closest question I could find was this one... but does not cover my requirements obviously...
Storing single quotes in varchar variable SQL Server 2008
Thanks in advance.
You can do this using dynamic SQL:
DECLARE #ListValues VARCHAR(MAX)
,#SQL VARCHAR(MAX)
SELECT #ListValues = '''aaa'',''bbb'',''ccc'''
,#SQL = 'SELECT * FROM TABLEA WHERE FIELD1 IN ('+#ListValues+')'
EXEC (#SQL)
It doesn't work because the IN operator expects a list of items - here strings.
What you're supplying with your #ListValues variable however is a single string - not a list of strings.
What you could do is use a table variable and store your values in it:
DECLARE #ListOfValues TABLE (ItemName VARCHAR(50))
INSERT INTO #ListOfValues(ItemName)
VALUES('aaa'), ('bbb'), ('ccc')
SELECT *
FROM TABLEA
WHERE FIELD1 IN (SELECT ItemName FROM #ListOfValues)
Build your whole SQL query dynamically (say it's stored in a string variable #sql),
and then execute it with EXEC (#sql). Better yet, use the sp_executesql SP
because this approach is more secure (less prone to SQL injection) than EXEC.
See: sp_executesql
The IN operator in SQLServer expect a list of values, your variable is a single string, the query parsed will be different
SELECT * FROM TABLEA WHERE FIELD1 IN ('aaa','bbb','ccc')
SELECT * FROM TABLEA WHERE FIELD1 IN ("'aaa','bbb','ccc'")
Attention: the double quotes are there only for readability, to get the string with single quote in it.
if you know a programming language the first one is like searching in an array, the second is a string.
To store a list in your variable it need to a table
DECLARE #varTable TABLE (field1 varchar())
So that you can use it in your IN
SELECT * FROM TABLEA WHERE FIELD1 IN (SELECT field1 FROM #varTable)
To add values to the table variable use an INSERT statament like usual for tables.

Declaring and Setting Variables of Different Data Types in Oracle SQL

I am currently writing a SQL query which first creates a lot of temporary tables using the WITH operator along with SELECT statements and then joins all of the temporary statements at the end.
All of my SELECT statements that create temporary tables depend on certain filters... so my query looks something liek
WITH
table_1 as (
SELECT product_id
avg(price)
FROM daily_sales
WHERE product_category = 1
AND sell_date BETWEEN TO_DATE('2012/01/07','YYYY/DD/MM') AND TO_DATE('2012/30/09','YYYY/DD/MM')
GROUP BY ds.product_id
),
table_2 as (....
),
SELECT FROM table_1 JOIN table_2....
I would like to run this query for ranges of 'sell_date' (a date, or a string) and different values of 'product_category' (an integer value).
Currently, I am replacing these manually but I am wondering if I can just declare replace these hard-coded values with variables, which I set at the top of my query.
I understand that this might have been asked before - but I am confused since there are multiple solutions that depend on the exact version of SQL that you are using and the types of variables that you are declaring.
In this case, I am looking for a solution that works in Oracle SQL, and where I can specify the type variable.
It depends how you're running your query.
If you're using an interactive client like SQL*Plus or TOAD you should use substitution variables:
WITH
table_1 as (
SELECT product_id
avg(price)
FROM daily_sales
WHERE product_category = &product_cat
AND sell_date BETWEEN TO_DATE('&start_date','YYYY/DD/MM') AND TO_DATE('&end_date','YYYY/DD/MM')
GROUP BY ds.product_id
),
You will be prompted to supply values for these variables each time you run the query. If you want to use the same values in multiple places then declare all the occurrences of a variable with a double ampersand - &&product_category - and then you only be prompted for it once. The SQL*Plus documentation has additional information: find out more.
If you're going to run the queries in a stored procedure then define the values as parameters ...
procedure process_sales_details
( i_product_category in number
, i_start_date in date
, i_end_date in date )
... which you reference in your query (wherever you declare it) ...
WITH
table_1 as (
SELECT product_id
avg(price)
FROM daily_sales
WHERE product_category = i_product_cat
AND sell_date BETWEEN i_start_date AND i_end_date
GROUP BY ds.product_id
),
Further to APC's answer, in SQL*Plus or SQL Developer you can also declare variables that you can assign values to in an anonymous PL/SQL block and then reference as bind variables in your plain SQL query:
variable v_product_cat number;
variable v_start_date varchar2(10);
variable v_end_date varchar2(10);
begin
:v_product_cat := 1;
:v_start_date := '2012/01/07';
:v_end_date := '2012/30/09';
end;
/
WITH table_1 as (
SELECT product_id
avg(price)
from daily_sales
where product_category = :v_product_cat
AND sell_date BETWEEN TO_DATE(:v_start_date,'YYYY/DD/MM')
AND TO_DATE(:v_end_date,'YYYY/DD/MM')
group by ds.product_id
)
...
Note the : before the variable name denoting a bind variable, and that the strings are not enclosed in quotes with this form. Unfortunately you can't declare a date variable, which would make this even neater.
And if you use substitution variables you can define them at the start so you aren't prompted; in this case you don't need to use the && notation either:
define v_product_cat=1
define v_start_date=2012/01/07
define v_end_date=2012/30/09
...
where product_category = &v_product_cat
and sell_date between to_date('&v_start_date','YYYY/DD/MM')
AND TO_DATE('&v_end_date','YYYY/DD/MM')
...
... which is covered in the documentation APC linked to.
You can add one or more common table expressions to encapsulate these:
with
cte_sell_dates as (
select date '2012-07-01' from_date,
date '2012-09-30' to_date
from dual),
cte_products as (
select 1 id from dual union all
select 28 id from dual),
... as (
select ...
from ...
where sell_date between (select from_date from cte_sell_dates) and
(select to_date from cte_sell_dates) and
product_id in (select id from cte_products )
...
... or use joins directly, instead of subqueries, of course.
Go for an Anonymous PL/sql Block and use a for loop where you can loop through all the different values.
Following is the Structure of pl/sql block:
DECLARE
<constant name> CONSTANT <data type> := <value>;
<constant name> CONSTANT <data type> DEFAULT <value>;
BEGIN
<valid statement>;
EXCEPTION
<exception handler>;
END;
Also you can go for a parametrized cursor where you can pass your values.

Changing Case of Strings (Lower to Upper) in SQL Server

I have 2 databases, one with lowercase data and another with uppercase data.
DECLARE #NAME VARCHAR(40)
SELECT #NAME = UPPER(SELECT NAME FROM DELETED)
By executing SELECT NAME FROM DELETED, I am selecting data that is lower case.
By executing SELECT #NAME = UPPER(SELECT NAME FROM DELETED), I would want to select uppercase data on the query inside the UPPER().
Question is can I use the UPPER() with the SELECT, like the query above?
How about
SELECT UPPER(NAME) FROM DELETED
instead of
UPPER(SELECT NAME FROM DELETED)
You'll need an extra pair of brackets
Select #NAME = UPPER((SELECT NAME FROM DELETED));
(Not that I'd do it that way, see Lukas's answer for a better approach).
Use
SELECT #pNAME = UPPER([NAME]) FROM DELETED