CREATING FUNCTIONS mysql - mysql

im using
CREATE FUNCTION UPDATEGames(usernameIN CHAR(15) ,opponientIN CHAR(15) ,mFilePath TINYTEXT,oFilePath TINYTEXT)
BEGIN
UPDATE games
IF (username = opponientIN AND FilePath = oFilePath) THEN SET opLastTurn = NOW(),Turn=Turn+1
ELSEIF (username = usernameIN AND FilePath = mFilePath) THEN SET myLastTurn = NOW(),Turn=Turn+1
END IF
END;
but it didnt worked, what am i ding wrong?and if it isnt possible to do it so then how can i simulate this logic?

Within the update you can only use the if function, not the if statement. The if statement can only be used to execute different sql statements. Furthermore, the where criteria must be used in the update to restrict the records to be updated.
So, there is no need to use if statement at all, just use two updates. There is no return value either, so I also changed function to procedure.
DELIMITER //
CREATE PROCEDURE UPDATEGames(usernameIN CHAR(15) ,opponientIN CHAR(15) ,mFilePath TINYTEXT,oFilePath TINYTEXT)
BEGIN
UPDATE games SET opLastTurn = NOW(),Turn=Turn+1 WHERE username = opponientIN AND FilePath = oFilePath;
UPDATE games SET myLastTurn = NOW(),Turn=Turn+1 WHERE username = usernameIN AND FilePath = mFilePath;
END//
DELIMITER ;

Related

want to Write a Stored Procedure in MYSQL [duplicate]

I have made a stored procedure. I want it to filter the data by different parameters. If I pass one parameter, it should be filtered by one; if I pass two, it should be filtered by two, and so on, but it is not working.
Can anyone help me please?
DROP PROCEDURE IF EXISTS medatabase.SP_rptProvince2;
CREATE PROCEDURE medatabase.`SP_rptProvince2`(
IN e_Region VARCHAR(45)
)
BEGIN
DECLARE strQuery VARCHAR(1024);
DECLARE stmtp VARCHAR(1024);
SET #strQuery = CONCAT('SELECT * FROM alldata where 1=1');
IF e_region IS NOT NULL THEN
SET #strQuery = CONCAT(#strQuery, ' AND (regionName)'=e_Region);
END IF;
PREPARE stmtp FROM #strQuery;
EXECUTE stmtp;
END;
AFAIK, you can't have a variable argument list like that. You can do one of a couple of things:
Take a fixed maximum number of parameters, and check them for null-ness before concatenating:
CREATE PROCEDURE SP_rptProvince2(a1 VARCHAR(45), a2 VARCHAR(45), ...)
...
IF a1 IS NOT NULL THEN
SET #strQuery = CONCAT(#strQuery, ' AND ', a2);
END IF;
If you need predetermined fields to which the criteria in the argument apply (like the e_Region parameter in your existing code), then you modify the CONCAT operation appropriately.
Possible invocation:
CALL SP_rptProvince2('''North''', 'column3 = ''South''')
Take a single parameter that is much bigger than just 45 characters, and simply append it to the query (assuming it is not null).
Clearly, this places the onus on the user to provide the correct SQL code.
Possible invocation:
CALL SP_rptProvince2('RegionName = ''North'' AND column3 = ''South''')
There's not a lot to choose between the two. Either can be made to work; neither is entirely satisfactory.
You might note that there was a need to protect the strings in the arguments with extra quotes; that is the sort of thing that makes this problematic.
I found a JSON-based approach which works with the latest MySQL/MariaDB systems. Check the link below (Original Author is Federico Razzoli): https://federico-razzoli.com/variable-number-of-parameters-and-optional-parameters-in-mysql-mariadb-procedures
Basically, you take a BLOB parameter which is actually a JSON object and then do JSON_UNQUOTE(JSON_EXTRACT(json object, key)) as appropriate.
Lifted an extract here:
CREATE FUNCTION table_exists(params BLOB)
RETURNS BOOL
NOT DETERMINISTIC
READS SQL DATA
COMMENT '
Return whether a table exists.
Parameters must be passed in a JSON document:
* schema (optional). : Schema that could contain the table.
By default, the schema containing this procedure.
* table : Name of the table to check.
'
BEGIN
DECLARE v_table VARCHAR(64)
DEFAULT JSON_UNQUOTE(JSON_EXTRACT(params, '$.table'));
DECLARE v_schema VARCHAR(64)
DEFAULT JSON_UNQUOTE(JSON_EXTRACT(params, '$.schema'));
IF v_schema IS NULL THEN
RETURN EXISTS (
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE
TABLE_SCHEMA = SCHEMA()
AND TABLE_NAME = v_table
);
ELSE
RETURN EXISTS (
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE
TABLE_SCHEMA = v_schema
AND TABLE_NAME = v_table
);
END IF;
END;

SQL Event - DELETE AND UPDATE rows on tables after UPDATE other table

I'd like to have a tricky SQL statement as an Event that runs every couple of minutes.
Currently, I'm doing so with Java, using 3 separate statements that executing sequentiality in a transaction connection.
Q: I don't know how to construct such an SQL statement without Java. If impossible to have a single SQL statement, I'd like to use transaction (as I'm using in Java) and rollback in case of failure in any of those separate statements.
My Case:
I have 3 tables: "Factory", "Plan", "Machine".
I want to do something as below:
1.
WHERE Machines.annualCheck == "TRUE"
SET Machine.status = "IN_ANNUAL_CHECK"
For machines that got updated I need to do the following:
2.1 Update the related factory
WHERE Factory.id == Machine.linkFactoryID
UPDATE Factory.totalActiveMachines = --1
2.2 Delete the upcoming plans that planned to be handled by the related machine
DELETE rows WHERE Plan.willHandleByMachineID = Machine.ID
p.s. I'm using MySQL
Thank you!
Update:
In following to Simonare suggestion, I tired to do the following:
DELIMITER $
CREATE PROCEDURE annualCheck(IN Machine_ID int, IN Factory_ID int)
BEGIN
UPDATE machine_table
SET machine_table.annualCheck = 'IN_ANNUAL_CHECK'
WHERE machine_table.machine_id = Machine_ID;
UPDATE factory_table
SET factory_table.totalActiveMachines = factory_table.totalActiveMachines - 1
WHERE factory_table.factory_id = Factory_ID;
DELETE FROM plan_table WHERE plan_table.assign_to_machine = Machine_ID
END$
DELIMITER $$
BEGIN
SELECT #m_id = machine_id, #f_id = link_factory_id
FROM machine_table
WHERE machine_table.annualCheck = 'TRUE';
END$$
CALL annualCheck(#m_id,#f_id)
I don't know why, but I'm running into syntax errors - one after the other.
It's my first time to use PROCEDURE and DELIMITER. Am I doing it right?
you can use stored procedure
delimiter //
CREATE PROCEDURE myProc (IN Machine_ID int)
BEGIN
UPDATE myTable
SET Machine.status = "IN_ANNUAL_CHECK"
WHERE Machines.annualCheck == "TRUE";
Update the related factory
WHERE Factory.id == Machine.linkFactoryID
UPDATE Factory.totalActiveMachines = totalActiveMachines -1;
DELETE FROM Plan WHERE Plan.willHandleByMachineID = Machine_ID;
END//
then you can execute it either from mysql
CALL simpleproc(#a);
or from Java
It is also possible to create trigger on the Machine table, something like this:
CREATE TRIGGER `TRG_Machines_AfterUpdate` AFTER UPDATE ON `Machine` FOR EACH ROW BEGIN
IF OLD.annualCheck = 'TRUE' AND NEW.annualCheck = 'IN_ANNUAL_CHECK' THEN
UPDATE
Factory
SET
totalActiveMachines = totalActiveMachines - 1
WHERE
id = NEW.linkFactoryID
;
DELETE FROM
Plan
WHERE
willHandleByMachineID = NEW.ID
;
END;
END
So you can just issue normal update:
UPDATE Machine SET annualCheck = 'IN_ANNUAL_CHECK' WHERE annualCheck = 'TRUE'

MySql Stored procedure WHERE "variabilised" according to a parameter

I'm totally new with stored procedure and I'm trying to understand its basic concepts. This is my first one and of course there is something wrong.
Basically the query is going to be the same (the original is more complex and there are other operations) but the WHERE clause changes according to the selType param. So what I'm trying to do is a sort of "variabilisation" of the WHERE clause according to the param value.
I don't know whether this is the correct approach and, if yes, what's wrong with it.
DELIMITER //
CREATE PROCEDURE `testProcedure` (IN addressId INT, IN selType BOOLEAN)
BEGIN
DECLARE whereUserCriteria VARCHAR(127);
IF selType = 1 THEN
SET whereUserCriteria = CONCAT('address_id = ', addressId);
ELSE
SET whereUserCriteria = 'address_id = 1';
END IF;
SELECT whatever
FROM wherever AS ad
WHERE whereUserCriteria ;
END //
It's nice to see that when it's not variabilised, it works perfectly but, as soon as i use a variable to make it dynamic, it stops working.
Of course this is a mere example aimed to understand what's the best approach in cases like this.
You can prepare query concatenating the queries and condition together and execute that using Prepared Execute statement as follows(as mentioned in the comment above):
DELIMITER //
CREATE PROCEDURE `testProcedure` (IN addressId INT, IN selType BOOLEAN)
BEGIN
DECLARE whereUserCriteria VARCHAR(127);
IF selType = 1 THEN
SET whereUserCriteria = CONCAT('address_id = ', addressId);
ELSE
SET whereUserCriteria = 'address_id = 1';
END IF;
SET #myQuery = '';
SET #myQuery = CONCAT("SELECT whatever FROM wherever AS ad
WHERE ",whereUserCriteria,") ;
PREPARE stmQuery FROM #myQuery;
EXECUTE stmQuery;
DEALLOCATE PREPARE stmQuery;
END //
DELIMITER ;
You probably want do dynamic query.
But you can rewrite your sample using CASE like this (but not sure if that is what you want):
SELECT whatever
FROM wherever AS ad
WHERE address_id = CASE WHEN selType = 1
THEN addressId
ELSE 1
END;

how to handle \ in query mysql

I have a procedure in which I am making query as string then prepare query and execute.
Here is the procedure
CREATE DEFINER=`root`#`%` PROCEDURE `dim_add_customer`(
IN _customer_id BIGINT(20) ,
IN _first_name VARCHAR(50) ,
)
BEGIN
SET #_query := CONCAT('first_name = "',_first_name,'"');
SET #_query := CONCAT('UPDATE customer_detail SET ',#_query,' WHERE customer_id = ',_customer_id);
PREPARE stmt FROM #_query;
END$$
DELIMITER ;
Now when I call
call dim_add_customer(1,'abc\\')
Then there is issue in creating string query.The query it made
UPDATE customer_detail SET first_name = "abc\" WHERE customer_id = 1
is there any best solution to solve this ?
You shouldn't build the queries by concat.
You should use the parameters in the query like
SET #_query="UPDATE customer_detail
SET first_name=#_first_name
WHERE customer_id = #_customer_id"
I'm not sure if you can declare your variables directly from the input parameters like
CREATE DEFINER=`root`#`%` PROCEDURE `dim_add_customer`(
IN #_customer_id BIGINT(20) ,
IN #_first_name VARCHAR(50) ,
)
or you have to
SET #_customer_id = _customer_id
SET #_first_name = _first_name
CAVEAT: I'm used to the MsSql-way of creating procedures with variables; I might have misunderstood something, but at least creating sql by concat should be your last resort.
Creating queries by concat is the equivalent of
x=1
q=concat("y=",x,"+2")
eval (q)
instead of
x=1
y=x+2

MySQL Stored Procedure Search another table

I am totally new to Stored Procedures, but know that this could be more efficient than trying to write PHP+MySQL code each time I need to do something like this.
I have two tables. CapitalAssets, Systems
I want find all CapitalAssets.ServerName that are not null
I have to link the two tables together, the Systems table has IP addresses, hostname.
I want to (row-by-row) grab CapitalAssets.ServerName and search Systems.hostname, IF it is found I want to link/print
CapitalAssests: Systems.id, Systems.hostname, Systems.IP, CapitalAssets.id, CapitalAssets.ServerName
Here is my start to my stored procedure, It is wrong. I do not now how to pass the Systems.hostname to do the search (where the ? is)
begin
declare GSATcur cursor for
'select id,NEName,ManagementAddress FROM GSAT WHERE NEName like ?';
declare CapitalCurr CURSOR FOR
'SELECT id,SystemName FROM CapitalAssets WHERE SystemName != ""';
DECLARE start INT DEFAULT 0;
DECLARE sysname_not_found BOOL DEFAULT FALSE;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET sysname_not_found = TRUE;
OPEN GSATcur;
OPEN CapitalCur;
loop1:
WHILE start < 5 do
FETCH SystemName INTO NEName;
IF sysname_not_found THEN
LEAVE loop1;
END IF;
END WHILE;
CLOSE CapitalCur;
CLOSE GSATcur;
END;
The two tables are in the same dB.
" grab CapitalAssets.ServerName and search Systems.hostname, IF it is found I want to link/print "
If this is the ultimate goal. Try this
SELECT * FROM Systems
WHERE hostname IN ( SELECT DISTINCT(ServerName)
FROM CapitalAssets WHERE ServerName IS NOT NULL );
UPDATE CapitalAssets
INNER JOIN Systems
ON Systems.hostname = CapitalAssests.ServerName
SET CapitalAssets.ipAddress = Systems.ipAddress;
UPDATE CapitalAssets
SET ipAddress = ( SELECT ipAddress
FROM Systems
WHERE Systems.hostname = CapitalAssests.ServerName );