EXECUTE IMMEDIATE PL/SQL - sql

Let's say sStorecode is: 00020
The following just executes the select statement to get the accountid at another database STORE in the table STOREINFO, for example connecting to p008081 (where 008 is the substring of the sStorecode and 081 is what I am joining below),
but I am getting errors for some reason (Invalid SQL Statement), can someone help?
EXECUTE IMMEDIATE 'select AccountID from STOREINFO#STORE.p'||substr(sSTORECODE,3,3)||'081';
Thanks in advance!

EXECUTE IMMEDIATE is a PL/SQL command. In PL/SQL, the result of a SELECT statement needs to go somewhere. But it your statement, you don't specify where it should go.
So if you expect a single row, you could write:
EXECUTE IMMEDIATE 'select AccountID from STOREINFO#STORE.p'||substr(sSTORECODE,3,3)||'081'
INTO l_account_id;
l_account_id is a local PL/SQL variable.
If you expect several row, you could use
EXECUTE IMMEDATE ... BULK COLLECT INTO l_account_tab;
l_account_tab is a PL/SQL collection variable.
Or if you want to work with cursors, you can write:
OPEN account_id_cv FOR 'select AccountID from STOREINFO#STORE.p'||substr(sSTORECODE,3,3)||'081';
account_id_cv is a REF CURSOR variable.

Seems like that should be something like this instead:
'select AccountID from STORE.STOREINFO WHERE sStorecode = ''p'||substr(sSTORECODE,3,3)||'081''';

Related

DB2 SQL considers IF ELSE condition a DDL statement?

I am trying to use a simple IF ELSE query to test a feature with DB2 SQL. However when I attempt to execute it, I run into an error stating that I am not allowed to execute DDL statements.
What is throwing me off is that as far as I know, only database structure altering statements are considered DDL statements.
What gives?
Code:
IF 'True' = 'True' THEN
SELECT * FROM RM_TRANSACTION
FETCH FIRST 2 ROWS ONLY
FOR READ ONLY WITH UR
ELSE
SELECT * FROM RM_TRANSACTION
FETCH FIRST 4 ROWS ONLY
FOR READ ONLY WITH UR
END IF
https://imgur.com/a/58RYjpu
The problem is that you can’t ‘select to nowhere’ in a compound statement in DB2. Db2 CLP can return you the result set of a single sql statement, but it doesn’t try to do the same for select statements in a compound statement.
If you want to print the result set from a select statement in a compound statement, you can, for example, declare a cursor, fetch it in a loop, and use dbms_output.put_line calls to print the values of variables.

Execute stored procedure before select

I am trying to reset my random number seed before executing a SELECT FROM. However, every time I run it, I have to run both statements separately. Ideally, I would like to have the following work:
BEGIN
exec dbms_random.seed(6);
SELECT * FROM myTable
ORDER BY dbms_random.value()
END
I get an error Encountered the symbol DBMS_RANDOM when expecting one of the following :=.(#%; however if I only run exec dbms_random.seed(6); it works.
EXEC[UTE] is a SQLPLUS command, you can not use it into a PLSQL block.
Also, you need an INTO to use a SELECT query within a PLSQL block. If your query can give more than one row, you woud have to use a BULK COLLECT INTO.
Your code could be something like:
DECLARE
something myTable%rowtype;
BEGIN
dbms_random.seed(6);
SELECT *
INTO something
FROM myTable
ORDER BY dbms_random.value();
END;
However, I do not recommend using things like select *; it would be better to explicitly write the columns you need to get.
Also what's the use of an order by in a select into statement which is defined to only return 1 row?
It seems you want to select 1 random row of many which needs a cursor like so:
DECLARE
CURSOR something_cur IS
SELECT *
FROM myTable
ORDER BY dbms_random.value();
something_rec something_cur%ROWTYPE;
BEGIN
dbms_random.seed(6);
OPEN something_cur;
FETCH something_cur INTO something_rec;
CLOSE something_cur;
END;
/

PLSQL Execute Immediate with Dynamic Using

I am dynamically building a search query with bind variables with at least 1 and at most 7 different potential criteria. I know I can do this -
EXECUTE IMMEDIATE sql USING bind_var1, bind_var2 or
EXECUTE IMMEDIATE sql USING bind_var3, bind_var5, bind_var7.
Is it possible to include the bind variables within the sql?
sql = 'SELECT * FROM table WHERE id = :bind_var1 AND name = :bind_var2 USING bind_var1, bind_var2'
and do
EXECUTE IMMEDIATE sql?
I want and need to dynamically build the USING piece instead of writing a lot of IF THEN statements.
According to your tags, I assume this will be used inside some kind of PL/SQL block. So, maybe are you looking for the open for statement.
This allows you to get a cursor on an dynamic query:
sql := 'SELECT * FROM table WHERE id = :bind_var1 AND name = :bind_var2';
open my_cursor for sql using bind_var1, bind_var2';
-- do whatever you need with your cursor
your USING bind_var1, bind_var2 pice of code should be out side os your sql string and come at the end of execute immediate statement and also for select senarios try to use dynamic sql for select with a cursor unless you want to select into a variable

'Execute Immediate' with Into Clause in HANA

I have a requirement where-in I need to read a table (table name provided as input parameter of the SP), store the results in a temp table and then store the count of the read table into a variable. Please advise how can this be achieved. I have been able to read the table and its count using dynamic query but am not able to put the results in a temp table/ variable. 'Select' and 'Into' clauses do not seem to be working with 'Execute Immediate'. Thanks.
It is not very clear to me exactly what is being asked, but you should be able to execute a SELECT statement in the following manner:
CREATE PROCEDURE p1(IN tablename VARCHAR) AS
BEGIN
execute immediate 'SELECT * FROM ' || :tablename;
END;
Then the following statements create a table and call the procedure to retrieve the result:
create table T (i integer);
insert into T values (123);
The following would produce a result set with one row/column with the value 123:
CALL p1('T')
Please note that with this type of functionality, you need to be very careful not to allow any user-provided input to be given directly to a procedure that uses EXECUTE IMMEDIATE to avoid the possibility of SQL injection attacks.

SQL SELECT dynamic from RDB$RELATION_NAME, to check tables integrity

I'm trying to create a stored procedure (or a a trigger, function, anything) to check if all the tables in a database is accessible.
My idea is to get all the tables in database, and then try to acess them with a simple select, if this succeeds for all the tables, everything is supposed to be ok.
I couldn't think of anything else to solve this problem, but I don't know how to do this, or all this intead.
1 - to get all the tables name I did:
SELECT RDB$RELATION_NAME TABLE
FROM RDB$RELATIONS
WHERE RDB$VIEW_BLR IS NULL
AND (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0)
ORDER BY TABLE
Now I just need to create the SELECT statement to each table, and run a query:
SELECT FIRST 1 * FROM [TABLE];
while it's ok, it continues, if all the tables are accessible, my database is ok.
Can anybody help me with this? Is this the correct aproach to solve this problem?
As a_horse_with_no_name commented, this is really strange request... if you see the table in the RDB$RELATIONS you can be pretty sure the table exists in the database. If the table is listed in the DB metadata but actually doesn't exist then the DB is corrupted and your idea to use select to check it's "accessibilty" is pointless... Also, the table might be there but the user might not have select right for it, IOW you need to take the user rights into account too.
Anyway, you can use the EXECUTE STATEMENT to execute dynamically built DSQL statement, something like
declare stmt varchar(1024);
declare ctab varchar(31);
BEGIN
FOR SELECT RDB$RELATION_NAME
FROM RDB$RELATIONS
WHERE RDB$VIEW_BLR IS NULL AND (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0)
INTO :ctab DO BEGIN
stmt = 'select ... from ' || ctab;
execute statement stmt;
END;
END
To check is the database corrupted you should use the gfix utility with -validate option.