Calculating age with currval in postgreSQL - database

I have created a database with a People table which contains all the information for people such as their first name, last name, gender,date of birth, and email. Each row in this table has a serial peopleID. I am trying to create a stored procedure and trigger to automatically calculate the age of a person that was just entered. I am trying to use currval to get the last inserted peopleID.
This is my stored procedure:
CREATE OR REPLACE FUNCTION PersonAge (peopleID INT)
RETURNS INTERVAL AS
$$
DECLARE
birthday date := (SELECT People.dateOfBirth
FROM People
);
BEGIN
RETURN age(birthday);
END;
$$
LANGUAGE plpgsql
This is my trigger:
CREATE TRIGGER CalculateAge
AFTER INSERT OR UPDATE ON People
FOR EACH ROW
EXECUTE PROCEDURE PersonAge( SELECT currval(‘people_id_seq’));
This is the error I am getting when I try to implement it with an insert statement:
ERROR: syntax error at or near "currval"
LINE 5: EXECUTE PROCEDURE PersonAge( SELECT currval('people_id_seq')...
^
********** Error **********
ERROR: syntax error at or near "currval"
SQL state: 42601
Character: 116

You pass arguments in not supported way, please read docs
Note that the function must be declared with no arguments even if it
expects to receive some arguments specified in CREATE TRIGGER — such
arguments are passed via TG_ARGV, as described below.
and
TG_ARGV[]
Data type array of text; the arguments from the CREATE TRIGGER
statement. The index counts from 0. Invalid indexes (less than 0 or
greater than or equal to tg_nargs) result in a null value.
(emphasis mine)

Related

Snowflake: Execution error in store procedure : SQL compilation error: Object does not exist or not authorized. At Statement.execute

I'm totally confused by the permission model of the Snowflake system. I created a database, created a stored procedure within that database, and tried to call that stored procedure all with the same user in the SYSADMIN role. I get the error "Execution error in store procedure: SQL compilation error: Object does not exist or not authorized. At Statement.execute"
I'm not even sure where to start. How does my user not have permission to a table that was created by said user?
Check the casing of the name of the objects you are referring to. If you for example created the table wrapped in double quotes, it's case sensitive. Snowflake automatically converts unquoted identifiers to UPPER case.
Example:
CREATE TABLE test1 (
test nvarchar)
CREATE TABLE "teSt2" (
test nvarchar)
-- This works
select * from test1
-- This doesn't work because the table was created wrapped in double quotes and with a capital S in the name
select * from test2
-- This doesn't work either because it will convert to UPPER
select * from teSt2
-- This works
select * from "teSt2"
A stored procedure returns a single row that contains a single column; it is not designed to return a result set. However, if your result set is small enough to fit into a single value of type VARIANT or ARRAY, you can return a result set from a stored procedure with some additional code- here
Hope this helps!
It works for delete statement! Example below:
use role sysadmin;
create or replace database DATA_IMPORTS_SO;
create or replace table ProductMaster_SO (id integer, name varchar);
insert into ProductMaster_SO values (1,'stackoverflow');
insert into ProductMaster_SO values (2,'stackoverflow');
select count(*) FROM DATA_IMPORTS_SO.PUBLIC.ProductMaster_SO;--2 rows
create or replace procedure Clenup_DI_Products()
returns string not null
language javascript
EXECUTE AS OWNER
as
$$
var sql_command =
"delete FROM DATA_IMPORTS_SO.PUBLIC.ProductMaster_SO";
try {
snowflake.execute (
{sqlText: sql_command}
);
return "Succeeded."; // Return a success/error indicator.
}
catch (err) {
return "Failed: " + err; // Return a success/error indicator.
}
$$;
call Clenup_DI_Products();
select count(*) FROM DATA_IMPORTS_SO.PUBLIC.ProductMaster_SO;--0 rows
Ultimately I was unable to find a reason that the stored procedure wouldn't work. I ended up dropping the table and recreating it with an all caps name. After that I was able to run the stored procedure with no issues.
I'm unclear if the fix was creating the table with a UCASE name or recreating it with a USER ROLE SYSADMIN command.
It may not be a problem with the case sensitivity of the table but it might be related to the rights of the stored procedure (Function) you created.
Changing your code as below might do the trick.
EXECUTE AS OWNER -- Present
EXECUTE AS CALLER -- Change
To understand more on owner's rights and caller's right of the Stored Procedure, please follow below link.
https://docs.snowflake.com/en/sql-reference/stored-procedures-rights.html
Two things to check.
Enclose the table name in double-quotes. Check case.
GRANT SELECT ON ALL TABLES IN SCHEMA "SCHEMA_NAME" TO ROLE PUBLIC;

trying to concat in the RAISE() function using || results in a syntax error

relevant documentation
I am trying to create a trigger that catches inserts into the Viewings table where the foreign key (viewings.location) does not correspond to an existing primary key in the Places table (places.location). The logic, from what I can tell, works as expected. However my issue comes from trying to concatenate the attempted value into the error-message in the raise function. Is this not allowed?
create trigger catchForeignKeyError BEFORE INSERT ON VIEWINGS
BEGIN
SELECT CASE
WHEN NEW.location NOT IN (SELECT PLACES.location FROM PLACES) THEN
RAISE(ABORT, 'Error: Insert into the VIEWINGS table references location '''||NEW.location||''' that is not found in the PLACES table.')
END;
END;
In the SQLite grammar, the second parameter of the RAISE() expression is not a string but a name:
RAISE(ABORT, some_error)
Identifiers can be quoted with double quotes, and for historical reasons, SQLite accepts a string (with single quotes) where an identifier is expected, but then it must be a single string, not a string expression composed of other values:
RAISE(ABORT, "some error")
There is no mechanism to get a dynamic value into the error message, except by creating a user-defined function for this.

ORA-14108: illegal partition-extended table name syntax

I have a requirement where I need to run a update script over multiple partitions of a table . I have written a script for it as below:
but it gives
ORA-14108: illegal partition-extended table name syntax
Cause: Partition to be accessed may only be specified using its name. User attempted to use a partition number or a bind variable.
Action: Modify statement to refer to a partition using its name
Any idea how can I circumvent this error?
DECLARE
TYPE partition_names IS varray(1) OF varchar2(20);
curr_partition partition_names;
LENGTH integer;
BEGIN
curr_partition :=partition_names('SM_20090731');
LENGTH := curr_partition.count;
FOR i IN 1 .. LENGTH LOOP
dbms_output.put_line('Current Partition name is: '||curr_partition(i));
UPDATE TABLE_Y PARTITION (curr_partition(i))
SET PARTITION_KEY=TO_DATE('2017-08-21','YYYY-MM-DD')
WHERE ORDER_ID IN
(SELECT ORDER_ID
FROM TABLE_X);
END LOOP;
END;
/
You will have to concatenate the partition name in and use dynamic SQL, i.e.
EXECUTE IMMEDIATE
'UPDATE TABLE_Y PARTITION (' || curr_partition(i) || ')
SET PARTITION_KEY=TO_DATE(''2017-08-21'',''YYYY-MM-DD'')
WHERE ORDER_ID IN
(SELECT ORDER_ID
FROM TABLE_X)';
Whenever you run a SQL SELECT query or an INSERT, UPDATE or DELETE statement from PL/SQL, bind variables are used to pass into the SQL engine the values of any PL/SQL expressions. In particular, a bind parameter will be used for curr_partition(i). However, it seems the PARTITION clause of such queries and statements doesn't support bind parameters. I guess that this is because Oracle tries to create an execution plan for the query or statement before it has the bind parameter values, but if the query or statement specifies a partition, that information is a critical part of the plan and hence cannot be provided in a bind parameter.

CREATE PROCEDURE in NetBeans IDE

I just wanted to add a simple procedure in Account table in Bank_Admin Schema.
The procedure adds some amount of money to the existing balance an account holder has. I guess, by reading the Sql command, you will figure it out.
But I am getting this error:
[Exception, Error code 30,000, SQLState 42X01] Syntax error:
Encountered "BEGIN" at line 2, column 1.
Line 2, column 1
Execution finished after 0.036 s, 1 error occurred
.Please help me with this code...
CREATE PROCEDURE deposit_in_bank (IN bank_account int, IN deposit_amount int)
BEGIN
UPDATE BANK_ADMIN.ACCOUNT SET balance = balance + deposit_amount WHERE account_no = bank_account
END
I'm assuming that defining a SQL stored procedure in NetBeans is the same as doing so directly as a SQL statement. If so...
I don't think your IN keywords are valid, all parameters are presumed to be input parameters unless specified as an output parameter.
As scsimon points out, you also need AS before your BEGIN.
I don't think you actually need your BEGIN and END at all either. Or the brackets around your parameters.
And I don't think you're writing your parameter variables correctly (they should be prefixed with #, so the following should work:
CREATE PROCEDURE deposit_in_bank
#bank_account INT,
#deposit_amount INT
AS
UPDATE BANK_ADMIN.ACCOUNT
SET balance = balance + #deposit_amount
WHERE account_no = #bank_account

Error while passing input parameters to stored procedure in oracle

I have written a stored procedure where i only give input parameters to insert records in to four tables but i am not able to find why its throwing below error, though i am passing correct number .any suggestions
also, purchase table is referencing foreign key of EID from employees table and purchase table is referencing foreign key of PID from products table
ans purchase table is referencing foreign key of CID from customers table ,
and after i pass parameters to stored procedure ,while insertion i want to give input via keyboard...
stored procedure as follows:
PROCEDURE add_purchase(e_id IN char,p_id IN char,
c_id IN char,pur_qty IN NUMBER) AS
Total_Price NUMBER(7,2);
ENAME VARCHAR2(15 BYTE);
TELEPHONE# CHAR(12 BYTE);
CNAME VARCHAR2(15 BYTE);
VISITS_MADE NUMBER(4,0);
PNAME VARCHAR2(15 BYTE);
QOH NUMBER(5,0);
QOH_THRESHOLD NUMBER(4,0);
ORIGINAL_PRICE NUMBER(6,2);
DISCNT_RATE NUMBER(3,2);
BEGIN
INSERT INTO employees (EID,ENAME,TELEPHONE#)
values (e_id,'&ENAME','&TELEPHONE');
INSERT INTO CUSTOMERS (CID,CNAME,TELEPHONE#,VISITS_MADE,LAST_VISIT_DATE)
VALUES (c_id,'&CNAME','&TELEPHONE','&VISITS_MADE',SYSDATE);
INSERT INTO PRODUCTS(PID,PNAME,QOH,QOH_THRESHOLD,ORIGINAL_PRICE,DISCNT_RATE)
VALUES (p_id,'&PNAME','&QOH','&QOH_THRESHOLD','&ORIGINAL_PRICE','&DISCNT_RATE');
select (pro.ORIGINAL_PRICE * (1 - pro.DISCNT_RATE)) into Total_Price
from purchases pur,products pro where pro.pid=pur.pid;
INSERT INTO purchases(EID,PID,CID,QTY,PTIME,Total_Price)VALUES
(e_id,p_id,c_id,pur_qty,sysdate,Total_Price);
EXCEPTION
WHEN OTHERS THEN
raise;
END add_purchase;
execution :
EXEC add_purchase ('e11','p011','c011',100);
error :
ORA-01722: invalid number
ORA-06512: at line 1
01722. 00000 - "invalid number"
*Cause: The specified number was invalid.
*Action: Specify a valid number.
An ORA-01722 ("invalid number") error occurs when an attempt is made to convert a character string into a number, and the string cannot be
With keyboard input the original price, discount rate, visits made values might cause this error when input is not actually a number.
But do stored procedures even allow keyboard input? Last time I checked they don't.
So this insert is apparently passing a literal string '&ORIGINAL_PRICE' where a NUMBER is expected.
INSERT INTO PRODUCTS(PID,PNAME,QOH,QOH_THRESHOLD,ORIGINAL_PRICE,DISCNT_RATE)
VALUES (p_id,'&PNAME','&QOH','&QOH_THRESHOLD','&ORIGINAL_PRICE','&DISCNT_RATE');
It seems that strings like '&ORIGINAL_PRICE' should always produce this sort of error when trying to convert to NUMBER,
So instead of referring to substitutions like '&ORIGINAL_PRICE' in the sp's insert values clause, for each substitution you would do something like...
accept o_price number format '99999.99' prompt 'Original Price:'
In the script that calls the sp, then call the sp passing &o_price as a parameter.
The the insert values clause in the sp would look like
INSERT INTO PRODUCTS(PID,PNAME,QOH,QOH_THRESHOLD,ORIGINAL_PRICE,DISCNT_RATE)
VALUES (p_id,PNAME,QOH,QOH_THRESHOLD,ORIGINAL_PRICE,DISCNT_RATE);
There would be no more & substitutions inside the sp's code.
ORIGINAL_PRICE and the other input parameters are already declared with the correct types. So you would then likely only get a conversion error if you type in bad input.
If columns such as ORIGINAL_PRICE are actually defined as character in the table then the problem might come in the expression (1 - pro.DISCNT_RATE).
So I think someone can give you a better answer, but I post mine as possibly useful.

Resources