I have a dynamic sql in a stored procedure with a MERGE statement and and executing it using EXECUTE IMMEDIATE <dynamic_sql>. When I run the merge query through the sql worksheet, it tells me the number of rows merged. How do I retrieve the same information through a dynamic sql?
I would appreciate any efforts towards this question.
After running any SQL statement (static or dynamic), the SQL%ROWCOUNT variable will tell you how many rows were affected.
EXECUTE IMMEDIATE l_sql_stmt;
l_rows_affected := SQL%ROWCOUNT;
Related
This is about Snowflake database.
I want to know if there is a way to get the last query id in current transaction.
I have a SQL stored procedure with a couple of delete and insert steps. In the beginning of the procedure, I start a transaction and I commit it at the end if no errors occur.
But to be certain that the procedure calculated the result and inserted some new rows in results table, I want to use the query id with result_scan to get the actual number of rows inserted.
I create a Snowflake connection from Python code and parallelly call stored proc with different input parameters.
The function last_query_id works at the session level, so it might return the query id from other parallel stored proc execution. For sequential execution, it works fine. But for multiple parallel executions this results in unexpected behavior.
I have also looked at the QUERY_HISTORY* functions but I don't see a relation between query history based on transaction id. There are only options to find queries for user/session etc.
In SQL Script stored procedures, there is a global variable named SQLID that holds the query ID of the last executed query in the procedure.
https://docs.snowflake.com/en/developer-guide/snowflake-scripting/query-id.html#getting-the-query-id-of-the-last-query
execute immediate $$
declare
query_id_1 varchar;
query_id_2 varchar;
begin
select 1;
query_id_1 := sqlid;
select 2;
query_id_2 := sqlid;
return [query_id_1, query_id_2];
end;
$$
;
Is it possible to write execute procedure (...with arguments...) (for Firebird 2.1 database) in Delphi 6 BDE TUpdateSQL.ModifySQL? I have tried, but I am receiving error message Update failed even for the simplest SQL procedure. So - are there some restrictions on the statement that can be executed in ModifySQL? I know (and I am using extensively), that it is possible to write execute procedure (and more complex statements) in the Delphi IBX TIBDataSet.ModifySQL (or in other similar properties of IBX components). Should I avoid execute procedure in TUpdateSQL or are there tricks that I should take into consideration?
René Hoffmann's idea was right - it is possible to execute procedure from the update statement. E.g. the following statement is accepted in ModifySQL:
update target_table set
id = :id,
field1 = :field1,
field2 = (select proc.field2 from additional_actions_procedure(:field2, :param1, :param2) proc)
where
id = :old_id
Delphi Unit DBTables contains the code that explains why exception is raised:
procedure TUpdateSQL.ExecSQL(UpdateKind: TUpdateKind);
begin
with Query[UpdateKind] do
begin
Prepare;
ExecSQL;
if RowsAffected <> 1 then DatabaseError(SUpdateFailed);
end;
end;
So affected rows counting happens. But apparently DBTables accounting of affected rows differs from the affected rows count in IBExpert. IBExpert counts the real affected rows be they affected by execute procedure, update statement or other statements. But DBTables counts (my guess) only rows of the target table that are updated by update statement. More investigation of Delphi code can reveal the more exact explanation.
This comment http://www.delphisources.ru/pages/faq/base/tupdatesql_many_queries.html suggest editing DBTables file.
I have more than 40 tables in RATOR_MONITORING schema for which the table name is starting from 'TEMP_'. I want to delete data from all such tables at once in a single query instead of using delete statement for each and every table. I dont even want to generate statements. I can create anonymous block if required but dont know how to do that. I tried below query but its not working.
Delete from RATOR_MONITORING_CONFIGURATION.'%TEMP_';
If you want to delete all the rows, then better use TRUNCATE, it will reset the high watermark. But remember, truncate is a DDL statement, and thus there will be an implicit commit; With DELETE you can commit manually after validation.
Although, I would not do that in a production environment. If it is something you are doing in test environment to build test data, then you could (ab)use EXECUTE IMMEDIATE.
For example, execute the following anonymous block as RATOR_MONITORING user:
DECLARE
v_sql VARCHAR2(100);
BEGIN
FOR i IN
(SELECT table_name FROM user_tables where table_name like 'TEMP%'
)
LOOP
v_sql := 'TRUNCATE TABLE '||i.table_name;
EXECUTE immediate v_sql;
END LOOP;
END;
/
By the way, using a good text editor, it won't take more than a minute to build DELETE/TRUNCATE statements and do it in pure SQL.
How does one return the number of rows affected from an insert or update statement while inside a SAP HANA stored procedure?
In oracle one would use sql%rowcount but I can't find an equivalent for HANA in their documentation?
For example:
CREATE PROCEDURE procedure_name (p_input)
LANGUAGE SQLSCRIPT AS
BEGIN
define c integer;
insert into some_table values (somevalues);
c := sql%rowcount;
END
UPDATE:
I found the answer on an SAP thread finally. You can run this statement after the insert or update to get the rowcount:
SELECT ::ROWCOUNT into L_C FROM DUMMY;
Not trying to steal internet points, but this should have an answer that's not just in the description of the question. To select row count, use the following:
SELECT ::ROWCOUNT INTO someVariable FROM DUMMY;
DUMMY is a special keyword in HANA and is used to select variables vs selecting from a table. You cannot simply SELECT ::ROWCOUNT INTO someVariable in HANA.
Isn't there a problem with ::ROWCOUNT since it is a system variable, so using it by several sessions simultaneously could produce incorrect results?
I have a stored procedure which I am running from a .sql file which takes in inputs from the users and runs the procedure. The procedure runs many queries and inserts a row of values into the table. In the .sql file I have I would like to order the table by a certain column after I finish running the queries. Currently I have:
DECLARE
NAMEPARAM VARCHAR2(200);
VERSIONPARAM VARCHAR2(200);
STARTDATE DATE;
ENDDATE DATE;
BEGIN
NAMEPARAM := '&1';
VERSIONPARAM := '&2';
STARTDATE := '&3';
ENDDATE := '&4';
PROCEDURE(NAMEPARAM, VERSIONPARAM, STARTDATE, ENDDATE);
COMMIT;
Select * from TABLE_NAME
ORDER BY COLUMN_NAME ASC;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20101,SQLERRM);
END;
/
However It throws the error:
PLS-00428: an INTO clause is expected in this SELECT statement
I dont know why it needs an into clause. Help?
Edit:
To clarify I don't want to see an output of a sorted table I would like the table itself to be updated and sorted by the column in ascending order.
If you put a SELECT statement in a PL/SQL block, you need to do something with the results. If you're expecting exactly one row, you'd do a SELECT INTO a local variable. Assuming that you are expecting multiple rows, you could write a FOR loop that iterates over the rows or you could BULK COLLECT the rows into a PL/SQL collection. You could also open a SYS_REFCURSOR but since there is no way to return that from an anonymous PL/SQL block, that seems unlikely to be what you want.
My guess is that you want the SELECT statement to be outside the PL/SQL block and you want whatever tool you are using to execute the .sql script to run the PL/SQL block to populate the table and then run the SELECT statement, writing the results to whatever file/ console you are spooling output to.