I have three tables below:
I need to create a trigger to disallow students to take a class without completing their pre-requisites (must use a trigger). The trigger must return an error message "Missing Pre-req" when trying to insert a class without its proper pre-req.
So far, I wrote a command below:
create trigger checkPrereq
before insert on HW3.SCHEDULE
referencing new as newRow
for each row
When
(
select GRADE
from HW3.SCHEDULE
where HW3.SCHEDULE.ClassId =
(
select PrereqId from HW3.CLASS_PREREQ
where newRow.ClassId = HW3.CLASS_PREREQ.ClassId
)
) in ('F', null)
begin atomic
set newRow.Semester = null;
signal sqlstate 'KILLED' set message_text = ('Missing Pre-req');
end
but I got a warning:
DB21034E The command was processed as an SQL statement because it was
not a valid Command Line Processor command. During SQL processing it
returned: SQL0104N An unexpected token "GRADE" was found following
"ach row When (select". Expected tokens may include: ")". LINE
NUMBER=1. SQLSTATE=42601
I can not understand what was happening here. Could you please help fix this? Any help is appreciated!
Is it possible to issue a "Show Shares" function call in either a FUNCTION or PROCEDURE in Snowflake? Since there isn't a metadata object in the Informational schema to query information about shares we are looking for a way to create a UDF to obtain this metadata and act on the results.
When attempting to execute the following code:
CREATE OR REPLACE PROCEDURE get_share_metadata()
RETURNS VARIANT
LANGUAGE javascript
AS
$$
var x=snowflake.execute( { sqlText: "SHOW SHARES" } );
$$
;
call get_share_metadata();
The following error is returned:
Execution error in store procedure GET_SHARE_METADATA: Stored procedure execution error: Unsupported statement type 'SHOW SHARE'. At Snowflake.execute, line 2 position 20
You can execute a SHOW .... command inside of a stored procedure ONLY if the procedure is setup to be EXECUTE AS CALLER.
When executing as caller, the role executing the procedure must have privileges to execute the commands within the procedure.
Examples:
SHOW SHARES is only accessible to the ACCOUNTADMIN role (technically any role can run the command successfully but results are limited to only the accountadmin).
SHOW USERS is only able to be successfully executed with any role that has the MANAGE GRANTS privilege on the account.
Documentation:
https://docs.snowflake.net/manuals/sql-reference/stored-procedures-usage.html#label-owners-rights-stored-procedures
I am not sure about function vs. stored procedure for this, but depending on what you're trying to do, have you looked into just using RESULT_SCAN?
SHOW SHARES;
SELECT * FROM TABLE(RESULT_SCAN(last_query_id()));
I am doing a procedure migration in pl / sql (oracle) to sql / pl (DB2) and I don't know how to pass a subprocedure to DB2
As I am not a system administrator I cannot change DB2 to be pl / sql compatible
EXAMPLE
create or replace PROCEDURE "SP_NOSTRADAMUS_PRODUTO"
AS
V_EXISTE_TAB NUMBER := 0;
PROCEDURE PR_HIRQ_PRODUTO_OR
AS
BEGIN
END
If your Db2-server runs on Linux/Unix/Windows, in ANSI SQL PL, if you have a local procedure nested within the body of another SQL PL procedure (or compound statement), then you use the DECLARE keyword to define the local procedure. This is supported by Db2-LUW in versions v10.1 and higher.
If you have very many Oracle PL SQL stored procedures, please discuss with your solution architect (if you have one) and your DBA about the possibility of configuring your Db2 server to support Oracle compatibility . This may save you some money.
You can see the Db2 syntax for SQL PL here (be sure to select the correct version of your Db2-server product in the pull down list).
There are some restrictions on local procedures, so study the documentation carefully. But your local procedure can access variables and objects defined in surrounding block(s) that are in scope.
Your example might look like this in ANSI SQL PL:
create or replace PROCEDURE "SP_NOSTRADAMUS_PRODUTO"
begin
declare V_EXISTE_TAB integer default 0;
declare PROCEDURE PR_HIRQ_PRODUTO_OR
BEGIN
-- body of pr_hirq_produto_or procedure
END;
-- body of sp_nostradamus_produto procedure
END
#
Db2 does not have subprocedures, not even sure why oracle would. In db2 you just create the 'sub' procedures as regular procedures and then 'CALL' them.
create procedure a( ....
create procedure b ....
create procedure main(...)
begin
call a(...);
call b(...);
end
I am trying to create a trigger that copys a newly INSERTED and/or UPDATED record from one table to a History version of this table. The purpose is to keep a record every time a record in a table is inserted and/or updated.
This is the Create Trigger statement syntax that I have, following the IBM Db2 Trigger site.
CREATE TRIGGER "TADB2"."HIST_CSEMASTER_Z_LOG"
AFTER UPDATE ON TADB2.CSEMASTER_Z
REFERENCING NEW AS N
FOR EACH ROW
BEGIN ATOMIC
INSERT INTO TADB2.HIST_CSEMASTER_Z
values (N.CSEMASTERID, N.CURRID, N.SUBCURRID, N.EXPIREDATE, N.CREATEDATE, N.CUSTVIEWNUM, N.CSEMSTRNAME, N.JOINCODE, N.CONTACTCOUNTRYCD, N.CONTACTSERIALNUM, N.AUDIENCECD, N.SPONSORNAME, N.AVAILABLEDATE, N.OWNERCOUNTRYCD, N.OWNERSERIALNUM, N.PRMWWCHAPTERID, N.PRMWWSUBCHAPTERID, N.SECWWCHAPTERID, N.SECWWSUBCHAPTERID, N.INTRANETIND, N.TINSERTTS, N.TLASTUPDTS, N.IBM_TRADEMARK, N.OTHER_TRADEMARK, N.INTERNETIND, N.BRANDID, N.BUSINESSID, N.LIFECYCLE_STATUS);
END;
The error I am receiving is:
[Code: -104, SQL State: 42601] An unexpected token "END-OF-STATEMENT" was found following "N.LIFECYCLE_STATUS)". Expected tokens may include: "".. SQLCODE=-104, SQLSTATE=42601, DRIVER=3.72.44
I've tried:
Removing the END
Removing the semi-colon after the END
Removing the semi-colon after the N.LIFECYCLE_STATUS);
Any help would be great! Thank you.
I highly recommend Db2 Temporal Tables for that. If you just use System Temporal functionality it would provide already the functionality you describe.
Worth to check it out
You must use different from ';' statement terminator in your tool.
Below is an example for DB2 Command Line Processor, which understands the first line as a directive to do this.
--#SET TERMINATOR #
CREATE TRIGGER "TADB2"."HIST_CSEMASTER_Z_LOG"
AFTER UPDATE ON TADB2.CSEMASTER_Z
REFERENCING NEW AS N
FOR EACH ROW
BEGIN ATOMIC
INSERT INTO TADB2.HIST_CSEMASTER_Z
values (N.CSEMASTERID, N.CURRID, N.SUBCURRID, N.EXPIREDATE, N.CREATEDATE, N.CUSTVIEWNUM, N.CSEMSTRNAME, N.JOINCODE, N.CONTACTCOUNTRYCD, N.CONTACTSERIALNUM, N.AUDIENCECD, N.SPONSORNAME, N.AVAILABLEDATE, N.OWNERCOUNTRYCD, N.OWNERSERIALNUM, N.PRMWWCHAPTERID, N.PRMWWSUBCHAPTERID, N.SECWWCHAPTERID, N.SECWWSUBCHAPTERID, N.INTRANETIND, N.TINSERTTS, N.TLASTUPDTS, N.IBM_TRADEMARK, N.OTHER_TRADEMARK, N.INTERNETIND, N.BRANDID, N.BUSINESSID, N.LIFECYCLE_STATUS);
END#
I'm using SQL Server 2008 R2 on a Windows 7 box. I have created a stored procedure to run the SQL command EXECUTE AS USER:
CREATE PROCEDURE dbo.ImpersonateUser
AS
BEGIN
EXECUTE AS USER = 'UserName';
END
Then, I'm trying to see if I am impersonating the user...
PRINT CURRENT_USER;
EXEC ImpersonateUser;
PRINT CURRENT_USER
...and the result is...
dbo
dbo
...when I want it to be...
dbo
UserName
This doesn't work, of course, because the EXECUTE AS USER statement is only valid inside the stored procedure ImpersonateUser. My question is this: Is it possible for the stored procedure ImpersonateUser to affect the calling context (session)? I want to encapsulate (and hide) other logic in the stored procedure.
It is not possible. Any EXECUTE AS change is automatically reverted at the end of a procedure.
Other things that dont live past the scope of the procedure are changes using the SET command and #TempObjects.
However, what you could do is encapsulate the logic that needs to be executed under the different security context in a procedure and then call that from within the procedure that changes the context. Something like:
CREATE PROCEDURE dbo.CallWithImpersonateUser
#ProcedureName
AS
BEGIN
EXECUTE AS USER = 'UserName';
EXEC #ProcedureName;
END;
Answer by Sebastian is correct, but still you have to grant impersonate for calling user.
Syntax can be found here
GRANT IMPERSONATE ON LOGIN::[login_to_be_impersonated] to [login1];
GO