I'm trying to create a trigger on derby which simply calls a procedure. The stored procedure does not change anything and gets no parameters. It simply check that the time is within an interval (for example between 08:00 and 16:00). On creation of trigger i receive the following error:
"42Z9D: Procedures that modify SQL data are not allowed in BEFORE triggers."
But the procedure makes no changes.
When defining a procedure one should specify if the procedure modifies data or not. If it executes any sql or not. As mentioned in the link provided above by Bryan I should use one the options:
{ NO SQL | MODIFIES SQL DATA | CONTAINS SQL | READS SQL DATA }
If you dont use this options the default value will be assumed that is CONTAINS SQL.
Related
We have a master stored procedure that loops through a table and for each row calls a stored procedure based on data from that table. There is likely to be a lot of rows and so we are worried about the the master stored procedure timing out due to the time it would take to loop through all of the rows.
The stored procedures called do not have a dependency on each other so we would like to speed up the process by executing the stored procedures without waiting for the previous one to finish. Is there a way to achieve this in snowflake?
Javascript stored procedures are single-threaded so there is no way to get them to run parts of their code in parallel.
You might be able to improve performance by changing your design, for example by running instances of the SP via tasks as you can get tasks to run in parallel
We have a master stored procedure that loops through a table and for each row calls a stored procedure based on data from that table.
Having one stored procedure call others will be single threaded. You can do this instead:
Create a task for each of your child stored procedures. Set its schedule to 1 minute; specify no overlapping execution, and do not enable it.
Have your main stored procedure read from the table that drives it.
Instead of having your main stored procedure call other stored procedures, have it alter their tasks to resume them.
The first thing each child stored procedure should do is to run a SQL statement to alter their task disabling it.
This will allow asynchronous, parallel execution. The main stored procedure just needs to figure out what other stored procedures do or don't need to run and what their call parameters should be. It kicks off their execution by enabling the schedule for their task and moves on to the next code statement. A minute later, the child stored procedure starts and disables its schedule so when it completes it won't run again until the main stored procedure alters its task back to enabled.
Your task create statements for the child stored procedures should be something like this:
create or replace task MY_SP_TASK
warehouse = 'MY_WAREHOUSE'
schedule = '1 MINUTE '
allow_overlapping_execution = false
as
call MY_SP('PARAM1', 'PARAM2')
If you need the main stored procedure to change the parameters in the call, you can have the main stored procedure run the "create or replace task" and change them. You'll then want to enable the task:
alter task MY_SP_TASK resume;
If you don't need to change the child's call parameters, you can just run the alter statement to resume it and that's all. Then on the child stored procedure among the first things the code should do is disable its own taskL
alter task MY_SP_TASK suspend;
I am trying to create a new field in a FireDAC-compatible database with this PROCEDURE:
PROCEDURE CreateField(Connection : TFDConnection ; CONST TableName : STRING; F : TFieldDefinition);
VAR
Table : TFDTable;
BEGIN
Table:=TFDTable.Create(NIL);
TRY
Table.Connection:=Connection;
Table.TableName:=TableName;
Table.FieldDefs.Updated:=FALSE;
Table.FieldDefs.Update;
Table.FieldDefs.Add(F.FieldName,F.FieldType,F.MaxLen,NOT F.Nullable);
// Commit my changes to the database //
FINALLY
FreeAndNIL(Table)
END
END;
where
TYPE
TFieldDefinition = CLASS
PUBLIC
FieldName : STRING;
FieldType : TFieldType;
MaxLen : Integer;
Nullable : BOOLEAN;
END;
but I can't seem to "Commit" my changes back to the database (ie. end up executing an ALTER TABLE ADD [COLUMN] statement).
How do I commit my changes to the FieldDefs list of the table? Or is there some other way - using plain FireDAC - that I can use to create a new field in an existing table?
Note: There are already data in the table, so I can't simply "DROP" and then "CREATE" the table again.
FireDAC should understand the sytax used by the supported databases and use the appropriate syntax and decoration. See the documentation here: http://docwiki.embarcadero.com/RADStudio/Sydney/en/Preprocessing_Command_Text_(FireDAC)
TFieldDef is an internal descriptor of the fields in a TDataSet, it's not going to be used to update the table structure automatically. (Although you could write your own procedure that compares your TFieldDefs to the FireDAC MEta Data and creates the DDL (Data Definition Language) statements you need to execute in a TFDCommand ... )
To alter that table structure you will need to provide the DDL (SQL) statement that you execute with TFDCommand - the 'preprocessing' link above will explain how to write it in a dialect abstracted way.
If you use the appropriate FireDAC description it will automatically put in the appropriate SQL decoration for you so the syntax is valid. Depending on your SQL dialect and the FireDAC driver you may hit limitations. (For example using the ODBC driver FireDAC generally won't know the specific details of the underlying database - we had to implement a solution for SAP HANA which had exactly this challenge).
Bear in mind that some SQL dialects support features that others don't - so for example it's not safe to assume that you can position a column when you add it (which MySQL supports for example) as not all dialects allow that in an ALTER TABLE statement.
I'm trying to write a procedure that creates users, roles and warhouse. This procedure is executed with a high privilege user with ACCOUNTADMIN role
USE ACCOUNT_ADMIN;
USE WAREHOUSE PROVISIONER;
CREATE or replace PROCEDURE TEST()
RETURNS VARCHAR
LANGUAGE javascript
AS
$$
snowflake.execute({ sqlText: "CREATE OR REPLACE WAREHOUSE test;"});
return "";
$$
;
Now if I query the current warehouse:
SELECT CURRENT_WAREHOUSE();
I get PROVISIONER
If I now call the procedure
CALL TEST();
The warehouse has changed
SELECT CURRENT_WAREHOUSE();
Now returns TEST
Is this the normal behaviour? This is an issue because the warehouse is changed outside of the procedure, and I cannot use the "USE WAREHOUSE" statement inside a procedure.
Is there another way to create WAREHOUSE from a procedure without changing the current warehouse?
Yes, this is expected. See the docs for background information.
One way to work around it would be to get the current warehouse at the beginning of your stored procedure, and set it again as the current one at the end of the stored procedure.
I'm creating Stored Procedures to replace Legacy app programs for an IBM i. I'm calling the stored procedure from a Java Web App. I'm using the jt400 JDBC driver
My JDBC URL is jdbc:as400://myhost/;libraries=*LIBL,MYLIB;prompt=false
The stored procedures can call stored procedures
The initial stored procedure call completes normally if it does not make further stored procedure calls
If the stored procedure makes a call to other stored procedures it fails with
com.ibm.as400.access.AS400JDBCSQLSyntaxErrorException: [SQL0204] MY_SP in MYLIB type *N not found.
If I hard code a schema in the stored procedure call statement, the call completes normally.
I want to have the called stored procedures use the same schema as the caller
You need to SET PATH = "MYLIB"
When I am using SQuirreL to call a stored procedure, I need to use the SET PATH statement to get it to find the stored procedure. I don't know if that is because my library list is bad or what, but the current schema is not used to find an unqualified stored procedure.
I actually had this same problem, the stored procedure uses your job description library list. You need to edit that you can use TAATOOL CHGLBLJOBD. I am not in front of an iSeries at the moment but I believe the command was either EDTJOBDLIB or EDTJOBDLIBL WRKJOBDLIBL. It is some variation of that.
I have a stored procedure that uses table variables to create a query and runs perfectly when executing in SQL Server Management Studio. However, the column referring to this table variable does not display when running the stored procedure in Query Designer.
I have used this method on many other reports without issue, but cannot figure out why the value will display in SSMS and not in SSRS.
After a fresh nights sleep, I realized it was how a parameter was being passed to the Sub Stored Procedures. The main stored procedure had a where clause that contained a "LIKE #Parameter" but the Sub Stored Procedure contained an "= #Parameter", so when a "%" was passed into the parameter the main Stored Procedure returned results, but nothing was displayed from the Sub Stored Procedure.
Simply just a case of making my job harder on myself...