i would like to set the Tablename as Variable
Why: i go from a oracle db to a mysql db via db link and in the mysql db i have some table-names which includes the date- example: data_20121126
here's my statement :
DECLARE
tbname VARCHAR2 (200);
BEGIN
SELECT ab.teste
INTO tbname
FROM (SELECT '"data_'
|| REPLACE (TO_CHAR (SYSDATE - 1, 'yyyy.mm.dd'),
'.',
'')
|| '"#myDB'
AS teste
FROM DUAL) ab;
SELECT * FROM tbname;
END;
could anybody help me please?
thanks in advance
It's not possible with static SQL (and I doubt that creating a new table for every day in your MySQL database is a sensible design approach).
If you really need to do this, you can
use dynamic SQL (EXECUTE IMMEDIATE / OPEN CURSOR FOR ...)
create a synonym once per day, pointing to the current table, and use that synonym in your query
You can't do this without resorting to dynamic SQL:
DECLARE
tbname VARCHAR2 (200) := '"data_'
|| TO_CHAR (SYSDATE - 1, 'yyyymmdd')
|| '"#myDB';
vMyVariable varchar2(10);
BEGIN
execute immediate "SELECT MyColumn
FROM " || tbname into vMyVariable ;
END;
Of course, this version assumes you'll be returning a single column from a single field into a variable. In all likelihood, you'll really want to return a ref cursor to your calling application.
Related
As we do in SQL, is it possible to pass variable on create statement as a table name in HANA?
I'm trying the below code but its throwing an error
CREATE PROCEDURE temp_table()
AS
table_name nvarchar(255);
BEGIN
table_name := '#TMP_TABLE'+ CURRENT_TIMESTAMP;
CREATE LOCAL TEMPORARY COLUMN TABLE :table_name(
SCENARIO varchar(64) NULL,
SCENARIO_CY varchar(64) NULL,
MONTH_NO numeric(4, 0) NULL
);
DROP TABLE :table_name;
END;
Please help me to find out a solution.
What you are looking for is Dynamic SQL. You will need to pass your SQL statement as a string to function EXEC or EXECUTE IMMEDIATE. The timestamp dependent name can be assembled by string concatenation.
In your code above your are using '+' to do string concatenation:
table_name := '#TMP_TABLE'+ CURRENT_TIMESTAMP;
IMHO this does not work on HANA. You should use a double pipe '||' instead:
table_name := '#TMP_TABLE' || CURRENT_TIMESTAMP;
I have to get the min and max dates for the data stored in all the database tables and display same along with the table names. I have written below function to do same
CREATE OR REPLACE FUNCTION data_bound(tbl_name IN VARCHAR2) RETURN VARCHAR2
AS
reqdates VARCHAR2;
BEGIN
EXECUTE IMMEDIATE 'SELECT concat(min(rec_date),max(rec_date)) from ' || tbl_name INTO reqdates;
RETURN reqdates;
END;
And I am trying to fetch data using below.
SELECT table_name, data_bound(table_name) FROM user_tables;
But my function does seems to be working, getting multiple errors. Please can you advise what's wrong here and if there's another better approach.
You can use:
CREATE FUNCTION data_bound(
tbl_name IN VARCHAR2
) RETURN VARCHAR2
AS
reqdates VARCHAR2(39);
BEGIN
EXECUTE IMMEDIATE 'SELECT TO_CHAR(min(rec_date), ''YYYY-MM-DD HH24:MI:SS'')
|| ''-'' || TO_CHAR(max(rec_date), ''YYYY-MM-DD HH24:MI:SS'')
FROM ' || DBMS_ASSERT.SIMPLE_SQL_NAME(tbl_name)
INTO reqdates;
RETURN reqdates;
END;
/
Which, if you have the table:
CREATE TABLE table_name (rec_date) AS
SELECT TRUNC(SYSDATE, 'YYYY') FROM DUAL UNION ALL
SELECT SYSDATE FROM DUAL;
Then:
SELECT data_bound('TABLE_NAME') FROM DUAL;
Outputs:
DATA_BOUND('TABLE_NAME')
2022-01-01 00:00:00-2022-04-19 18:57:25
db<>fiddle here
Error 1: data_bound() function is defined. data_retention() function is called
Error 2: tbl_name is taken as input, but not used (t_name is used once)
Error 3: 'from' keyword is missing in the execute immedeate statement
Error 4: 'into' keyword should be placed before 'from tableName'
I would like to read user query from variable as (:user_query:) and execute it - in Oracle it will be like:
DECLARE
ddl_qry CLOB;
user_query VARCHAR2(20) := 'SELECT 100 FROM dual';
BEGIN
ddl_qry := 'INSERT INTO a (v) VALUES ((SELECT CAST(( ' || user_query || ') AS NUMBER) as COUNTER FROM dual))';
EXECUTE IMMEDIATE ddl_qry;
END;
I need to insert result of user_query to table 'a'.
I don't care if it will fail or sth, but is this safe? :) Is there any option if string user_query with SQL will drop my database or do sth else?
Or sb can construct a query that will drop my database?
If we fix the (many) syntax errors in your PL/SQL block we come to:
DECLARE
ddl_qry CLOB;
user_query VARCHAR2(20) := '1024';
BEGIN
ddl_qry := 'INSERT INTO a (v) VALUES ((SELECT CAST(( :user_query ) AS NUMBER) as COUNTER FROM dual))';
EXECUTE IMMEDIATE ddl_qry USING user_query;
END;
/
It will work and there is not a SQL injection vulnerability as it uses a bind variable :user_query to input the value.
However, that does not mean that it is particularly good as you:
Do not need to use dynamic SQL;
Do not need to select from the DUAL table; and
Do not need to explicitly CAST the input to a NUMBER as, if the column you are inserting into is a NUMBER then, there will be an implicit cast.
So the above code can be simplified to:
DECLARE
user_query VARCHAR2(20) := '1024';
BEGIN
INSERT INTO a (v) VALUES ( user_query );
END;
/
There is still no SQL injection vulnerability and the query is much simpler.
db<>fiddle here
Update
in Oracle it will be like:
DECLARE
ddl_qry CLOB;
user_query VARCHAR2(20) := 'SELECT 100 FROM dual';
BEGIN
ddl_qry := 'INSERT INTO a (v) VALUES ((SELECT CAST(( ' || user_query || ') AS NUMBER) as COUNTER FROM dual))';
EXECUTE IMMEDIATE ddl_qry;
END;
That has huge SQL injection vulnerabilities.
If user_query is, instead, set to:
SELECT CASE
WHEN EXISTS(
SELECT 1
FROM users
WHERE username = 'Admin'
AND password_hash = STANDARD_HASH( 'my$ecretPassw0rd', 'SHA256' )
)
THEN 100
ELSE 0
END
FROM DUAL
If you get the value 100 then you know that:
There is a table called users;
It has columns username and password_hash;
There is an Admin user; and
You've verified their password.
Please don't use dynamic SQL and string concatenation if you do not need to.
In Oracle SQL statement I need to assign variable value from Select Statement. I am doing it according to line documentation but the variable value is empty.
In SQL server the following is what I need to do.
DECLARE #variable INT;
SELECT #variable= mycolumn from myTable;
In Oracle here is the output and query that I am having problem with. I am using Toad client.
My goal is to use the variable value as part of a query.
Here is a simple example intended use.
SELECT * FROM mytable WHERE DateField >= :varCurrMoDateBeg
DECLARE
varCurrMoDateBeg DATE;
varCurrMoDateEnd DATE;
BEGIN
SELECT MONTH_BEG_DATE INTO varCurrMoDateBeg FROM
(
SELECT
CALENDAR.MONTH_BEG_DATE MONTH_BEG_DATE
FROM
CALENDAR
WHERE
CALENDAR.CAL_TYPE='M'
AND (sysdate) BETWEEN CALENDAR.MONTH_BEG_DATE AND CALENDAR.MONTH_END_DATE
) ;
--DBMS_OUTPUT.PUT_LINE(varCurrMoDateBeg);
SELECT MONTH_END_DATE INTO varCurrMoDateEnd FROM
(
SELECT
CALENDAR.MONTH_END_DATE MONTH_END_DATE
FROM
CALENDAR
WHERE
CALENDAR.CAL_TYPE='M'
AND (sysdate) BETWEEN CALENDAR.MONTH_BEG_DATE AND CALENDAR.MONTH_END_DATE
);
--DBMS_OUTPUT.PUT_LINE(varCurrMoDateEnd);
END;
SELECT :varCurrMoDateBeg, :varCurrMoDateEnd from dual;
Online sources:
SELECT INTO Statement
https://docs.oracle.com/cd/B14117_01/appdev.101/b10807/13_elems045.htm
plsql - Declaring a variable and setting its value from a SELECT query in Oracle - Stack Overflow
Declaring a variable and setting its value from a SELECT query in Oracle
PL/SQL SELECT INTO Statement By Practice Examples
https://www.oracletutorial.com/plsql-tutorial/plsql-select-into/
Oracle Tutorials - Assign Query Results to Variables
http://dba.fyicenter.com/faq/oracle/PL-SQL-Assign-Query-Results-to-Variables.html
Using Toad, a small example
declare
v_var date;
v_bind date :=to_date('01.01.2020','DD.MM.YYYY');
v_stm varchar2(4000);
v_counter pls_integer;
begin
select sysdate into v_var from dual ;
dbms_output.put_line(v_var);
execute immediate ' select sysdate from dual ' into v_var ;
dbms_output.put_line(v_var);
-- with bind
v_stm := ' select count(*) from dba_objects where created > :1 ' ;
execute immediate v_stm into v_counter using v_bind;
dbms_output.put_line(v_counter);
end;
/
When I ran this code
As you can see, it is a very easy piece of code that shows how to use bind variables in PL/SQL.
You could create a function for each of the dates you want to use outside of your current PL/SQL block. Here is a rough example to demonstrate how that could be made to work.
CREATE OR REPLACE FUNCTION varCurrMoDateBeg
RETURN DATE
AS
dt_Work DATE;
BEGIN
-- Replace this with your query
SELECT SYSDATE INTO dt_Work FROM dual;
RETURN dt_Work;
END varCurrMoDateBeg;
/
SELECT varCurrMoDateBeg FROM dual;
I have below procedure for which i am passing db link as a parameter and create dynamic sql statement. While executing the procedure i am getting error as ORA-00904: "DB_CONNECTION_NAME": invalid identifier. I have declared the variable but still i am getting this error.
CREATE OR REPLACE PROCEDURE "EXT_SDR_RECEIVED"(in_db_link IN VARCHAR2)
AS
last_sm_id NUMBER := 0;
last_capt_date DATE;
l_sql VARCHAR2(5000);
db_connection_name VARCHAR2(100);
BEGIN
SELECT db_link INTO db_connection_name
FROM rator_monitoring_configuration.db_connection
WHERE db_link = in_db_link;
--DELETE DATA FROM TEMP_SDR_RECEIVED
DELETE FROM temp_sdr_received WHERE create_date < SYSDATE - 7;
-- first retrieve the last id (of the newest record) which has been imported at last extraction
SELECT last_task_id INTO last_sm_id
FROM capturing WHERE db_table = 'TEMP_SDR_RECEIVED';
SELECT capturing_date INTO last_capt_date
FROM capturing WHERE db_table = 'TEMP_SDR_RECEIVED';
dbms_output.PUT_LINE('DB' || db_connection_name);
-- retrieve all new records from remote SDR_O2 table and insert it into TEMP_SDR_RECEIVED where ID is greater than LAST_SM_ID
l_sql := 'INSERT INTO TEMP_SDR_RECEIVED(ID,RATING_CODE,A_NUMBER,CREATE_DATE,VOUCHER_ATTEMPT_ID,RATOR_BRAND_ID,BRAND_ID,STATUS_DESCRIPTION,ACCOUNT_PAYMENT_ID,SUBSCRIPTION_ID,DB_LINK)
SELECT SD.ID,SD.RATING_CODE,SD.A_NUMBER,to_date(substr(SD.ID, 1, 8), ''YYYYMMDD''),VA.ID,VA.BRAND_ID,BR.BRAND_ID,VA.STATUS_DESCRIPTION,VA.ACCOUNT_PAYMENT_ID,VA.SUBSCRIPTION_ID,DB_CONNECTION_NAME
FROM SDR_O2#' || db_connection_name || ' SD
JOIN VOUCHER_ATTEMPT#' || db_connection_name || ' VA
ON SD.ID = VA.SDR_ID,
RATOR_MONITORING_CONFIGURATION.BRAND BR
WHERE VA.BRAND_ID IS NOT NULL
AND BR.RATOR_BRAND_ID = VA.BRAND_ID
AND SD.RATING_CODE=''VOUCHER''
AND VA.STATUS_DESCRIPTION = ''USSD voucher''
AND SD.ID > LAST_SM_ID';
EXECUTE IMMEDIATE l_sql;
END ext_sdr_received;
You are referencing DB_CONNECTION_NAME in the select part of your dynamic query (look after VA.SUBSCRIPTION_ID). Do any of your 3 tables have that column? I suspect not.
I suspect that you wanted to select the value in the DB_CONNECTION_NAME variable instead. To do that, change that last part of the SELECT in your dynamic query like this:
'...,VA.SUBSCRIPTION_ID, ''' || DB_CONNECTION_NAME || '''
...
You may also want to look into how execute immediate supports parameter binding, so that, where possible, you can avoid having to write this ugly string concatenation code.
Also, I notice you are mixing join notations. That's asking for trouble. Stick to ANSI JOIN syntax.