I am trying to implement a procedure within mysql that returns the age based on a calculation.
The date of birth (DATE) is passed in and then the calculation is done. Should be relatively straight forward but I cannot seem to get it to work. I am not sure if this is an appropriate situation for a "select statement" and
I apologize if this is extremely simple but this is my first run at procedures.
If somebody could please tell me what I am doing wrong, it would be much appreciated.
Thanks!
P.S. I have a table called "PERSON" that contains the field "age" (int) which is currently empty until the stored procedure is called.
DELIMITER $$
CREATE PROCEDURE determineAge(IN birthDate DATE)
BEGIN
DECLARE today TIMESTAMP;
SELECT DATEDIFF(today,birthdate)/365 AS ageInYears
FROM PERSON;
END $$
DELIMITER ;
call determineAge('June 25, 1981');
This works. No need to declare "today" - just use a NOW() function in your query.
Also, no need to select FROM anything... you're just querying a single value.
Your date was formatted wrong (MySQL requires 'YYYY-MM-DD', and you want to floor the difference to get a whole number of years.
DELIMITER $$
CREATE PROCEDURE determineAge(IN birthDate DATE)
BEGIN
SELECT FLOOR(DATEDIFF(NOW(), DATE(birthdate))/365);
END $$
DELIMITER ;
CALL determineAge('1981-06-25');
Finally, you could theoretically return the year value as an OUT param if you wanted to, though a query result is just fine.
DELIMITER $$
CREATE PROCEDURE determineAge(IN birthDate DATE, OUT age INT)
BEGIN
SELECT FLOOR(DATEDIFF(NOW(), DATE(birthdate))/365) INTO age;
END $$
DELIMITER ;
There you go!
Related
I would like my website's users to submit data with my HTML form. However, I want each user to be limited to 5 submissions total. To do this, I'm using a MySQL DML trigger to limit my column "um_id" to only five rows per id. But, I know my syntax is wrong and I'm asking anyone here to help correct it so that it could actually work.
Right now I'm testing this in PHPMyAdmin and it will eventually be placed in my PHP file. So um_id will have a value and be concatenated with this SQL Trigger.
CREATE TRIGGER ml_trigger
BEFORE INSERT
ON ml_character;
BEGIN
IF ( SELECT . 'um_id' . COUNT(*) > 5 ) THEN ROLLBACK;
END IF;
Something like this:
DELIMITER $$
CREATE TRIGGER ml_trigger_bi
BEFORE INSERT
ON ml_character
FOR EACH ROW
BEGIN
-- get count of existing rows with same um_id
DECLARE li_cnt BIGINT;
SELECT COUNT(*) AS cnt
FROM ml_character t
WHERE t.um_id = NEW.um_id
INTO li_cnt ;
-- if already five rows, throw error
IF li_cnt >= 5 THEN
SIGNAL '45000' SET MESSAGE_TEXT = 'Already five rows in ml_character';
END IF;
END$$
DELIMITER ;
The value of um_id to be checked will come from the row being inserted; we reference that value as NEW.um_id.
I have one table called number_list which have columns like:
id, name, number, server, status, last_act, user_id, created_at, disable, notify,fcm
I want update last_act when there any changes in status column only. Currently its updating last_act whenever any changes in any column.
Let me know if its possible with MySQL. Thanks
Setting up a trigger like the following should accomplish what you have asked.
DELIMITER $$
CREATE TRIGGER number_list_update_trigger
BEFORE UPDATE
ON number_list
FOR EACH ROW
BEGIN
if (NEW.status = OLD.status) THEN
set NEW.last_act = OLD.last_act;
END IF;
END $$
DELIMITER ;
I am executing a PLSQL Block using OCI from my PHP site which is running some procedures inside. The final procedure is returning the inserted records rowid of a specific table.
BEGIN
proc1(1);
proc2(2, rowid_);
END;
What I want to do is, I want to get the primary key values of the record for this rowid?
Is there a way to run it somehow like below and get the select results out to PHP with oci_fetch_row or something?
BEGIN
proc1();
proc2(rowid_); -- out variable
SELECT column1, column2
FROM my_table
WHERE rowid = rowid_;
END;
There's a better way. Try something like:
DECLARE
nPK_col NUMBER;
nCol1 NUMBER := 1;
nCol2 NUMBER := 2;
BEGIN
INSERT INTO SOME_TABLE(COL1, COL2)
VALUES (nCol1, nCol2)
RETURNING PK_COL INTO nPK_col;
END;
This example assumes that the primary key column named PK_COL is populated in some way during the execution of the INSERT statement, e.g. by a trigger. The RETURNING clause of the INSERT statement specifies that the value of PK_COL from the inserted row should be put into the variable specified, in this case nPK_col. You can specify multiple columns and variables in the RETURNING clause - documentation here. You may need to put this into whatever procedure performs the actual INSERT and then add an OUT parameter to allow the value to be passed back to the caller - or use a FUNCTION instead of a PROCEDURE and have the primary key value be the return value of the FUNCTION.
Share and enjoy.
What is the purpose of OUT in MySQL stored procedures?
If I have a simple stored procedure which looks like this:
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `new_routine`(
IN iID int
)
BEGIN
select * from table1 where id = iID;
END
This would give me all the results I want by running:
call new_routine(7);
So why would I want/need to use OUT?
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `new_routine`(
IN iID int,
OUT vName varchar(100)
)
BEGIN
select name into vName from table1 where id = iID;
END
and call it like this
call new_routine(7, #name);
select #name;
Which will give me just the name instead of everything from the rows returned?
I've tried Googling, but clearly haven't asked Google the right question to get a clear answer.
As quoted from MySQL doc on PROCEDURE
For each OUT or INOUT parameter, pass a user-defined variable in the
CALL statement that invokes the procedure so that you can obtain its
value when the procedure returns. If you are calling the procedure
from within another stored procedure or function, you can also pass a
routine parameter or local routine variable as an IN or INOUT
parameter.
And later, an example:
mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)
-> BEGIN
-> SELECT COUNT(*) INTO param1 FROM t;
-> END//
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> CALL simpleproc(#a);
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT #a;
+------+
| #a |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
Yeah, you're right, with that second call you will now only get the name itself.
Out-Parameters for many people are generally considered bad practice, but they can be handy if you want a value that you can work with after the call (which could also be calculated by a function obviously). And in most cases there is a better way to achieve what you want without using out-parameters.
However the only "advantage" if you will is that you have a value in a variable instead of a result set which might seem more handy if you decide to use only that value further in your sql or whereever you want to work with it.
So in most cases you should really not use out-parameters, use functions instead.
If you have procedures that return result sets AND out-parameters try to break them down into smaller functions/procedures to avoid out-parameters, because it's just not nice to read and maintain ;)
Some documentation: http://dev.mysql.com/doc/refman/5.0/en/call.html maybe it will help, quote:
To get back a value from a procedure using an OUT or INOUT parameter,
pass the parameter by means of a user variable, and then check the
value of the variable after the procedure returns. (If you are calling
the procedure from within another stored procedure or function, you
can also pass a routine parameter or local routine variable as an IN
or INOUT parameter.) For an INOUT parameter, initialize its value
before passing it to the procedure. The following procedure has an OUT
parameter that the procedure sets to the current server version, and
an INOUT value that the procedure increments by one from its current
value:
CREATE PROCEDURE p (OUT ver_param VARCHAR(25), INOUT incr_param INT)
BEGIN
# Set value of OUT parameter
SELECT VERSION() INTO ver_param;
# Increment value of INOUT parameter
SET incr_param = incr_param + 1;
END;
The use of the OUT keyword is stated in the following article
13.2.1. CALL Syntax
CALL can pass back values to its caller using parameters that are
declared as OUT or INOUT parameters.
I want to put a timestamp when a specific column is updated.
For example:
column1: a value
dateColumn1: date column1 was updated
column2 : a value
dateColumn2: date column2 was updated
I use the function getTimestamp(), but it doesn't seem to work.
Can anyone advise me on how to do this in PHP and MYSQL?
Thanks.
If you want to do this only in the database, you could write a trigger that checks your conditions and updates specific timestamps if needed. But I'm assuming you don't want to fiddle around with triggers. Triggers have an advantage though: you can access the old and the new values of a row without having to write any php code.
Anyway, in case you need it here is some example code for a trigger (SQL, beware):
DELIMITER $$
DROP TRIGGER IF EXISTS Table1_UpdateTrigger $$
CREATE TRIGGER Table1_UpdateTrigger BEFORE UPDATE ON Table1
FOR EACH ROW BEGIN
IF OLD.column1 != NEW.column1 THEN
SET NEW.dateColumn1 = NOW();
END IF;
IF OLD.column2 != NEW.column2 THEN
SET NEW.dateColumn2 = NOW();
END IF;
END;
$$
DELIMITER ;
Substite Table1 with your real table names, column1, etc. with real column names.
The other way is to compare the old and the new values in php. E.g. do a query fetching the old data, compare the fields you want to check, and then do one update query per field that has changed to set the new timestamps.
UPDATE table
SET column1='new value', timestampcolumn=NOW()
WHERE ...
is one way. If you don't mind the timestamp changing anytime anything in the record is updated, then use the native "timestamp" field type, which'll update itself to "now" when the record's inserted or changed.
I prefer using the MySQL function NOW(), like so:
UPDATE table1 SET column2 = value, dateColumn2 = NOW() WHERE somethingsomething
Use a conditional statement. For example in the following trigger the 'password changed time' will be updated only when there is change in password column.
CREATE TRIGGER update_password
BEFORE UPDATE ON users
FOR EACH ROW
BEGIN
IF OLD.password <> NEW.password THEN
SET NEW.password_changed_on = NOW();
END IF;
END //