Is it possible to write compound statements in if condition -mysql ?
It is returning an error for me like:
[Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DECLARE n INT unsigned DEFAULT 0;
DECLARE i INT unsigned DEFAULT 0;
DECL' at line 40
Sombody please help
Here is the query I am using
...........................................
IF(tarif='LT')
THEN
CREATE TABLE costSlabs SELECT `Start`,`End`,Cost FROM energy_slabs where SiteId=NEW.SiteID and `Start` < totalUnits;
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
DECLARE newStart INT;
DECLARE newEnd INT;
DECLARE newCost DOUBLE;
DECLARE finalCost DOUBLE DEFAULT 0;
SELECT COUNT(*) FROM costSlabs INTO n;
SET i=0;
WHILE i<n DO
SELECT `Start`, `End`,Cost INTO newStart,newEnd,newCost FROM costSlabs LIMIT i,1 ;
IF(newEnd<totalUnits)
THEN
SET finalCost = finalCost + ((newEnd-newStart) * newCost);
ELSE
...........................................
The IF statement is valid within the context of a MySQL stored program (stored procedure, function or trigger). Outside of the context of a MySQL stored program, it isn't a valid SQL statement.
We're not seeing the context of these statements, but based on the reference to NEW. in the SQL SELECT, without any table or table alias named NEW, I'll assume that this SQL is in the context of a CREATE TRIGGER statement.
I suspect that the problem you are encountering is due to the semicolon delimiter, which effectively ends the CREATE TRIGGER statement. In order to create a trigger that includes semicolon characters, it's necessary to specify a different statement delimiter. For example:
DELIMITER $$
CREATE TRIGGER mytrig
BEFORE INSERT ON mytable
FOR EACH ROW
BEGIN
SET NEW.col1 = 'foo';
SET NEW.col2 = 'bar';
END$$
DELIMITER ;
The first statement specifies that $$ will be used as the delimiter to end a statement. With that set, the statements following will be read together as a single statement, until a $$ delimiter is encountered. That will end the statement, and allow it be executed. This basically prevents the semicolons within the trigger body from prematurely "ending" the statement.
Once the statements are completed, you can change the delimiter back to a semicolon.
The block of SQL text posted in the question is invalid on its own. I suspect that the syntax error is being returned from the execution of a CREATE TRIGGER statement, but that's just a guess, since there's not enough context in the question to make a conclusion.
Also, I believe that within a MySQL stored program (such as a TRIGGER), all of the DECLARE statements must appear before other statements, such as CREATE TABLE.
Related
I need to delete records from a staging table in a stored procedure. I then need to insert records into the same table. This must be done prior to using a cursor that loops through the records.
DELIMITER //
CREATE PROCEDURE Get_Employee_Records()
BEGIN
DECLARE rollingSum INT DEFAULT 0;
DECLARE theMonth varchar(3);
-- Delete & insert on Employee must be done prior to the select
DECLARE mycursor CURSOR FOR SELECT Tgrowth,TYear,myMONTH FROM Employee;
-- cursor body here
CLOSE mycursor;
END //
DELIMITER ;
When i place my insert & delete statements in the commented section i get
Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DECLARE mycursor CURSOR FOR SELECT Tgrowth,TYear,myMONTH FROM Employee' at line 63
Where would be the right place to place the insert & delete sql in the procedure. I could probably do this in a separate procedure but I want to know if i am missing something here.
In a begin...end block declarations must appear before any other code so
wrap the cursor section in a begin..end like so (btw you need to fix the code).
begin
DECLARE mycursor CURSOR FOR SELECT Tgrowth,TYear,myMONTH FROM Employee;
-- cursor body here
open mycursor;
CLOSE mycursor;
end;
There is almost never a reason to use cursors in sql - are you sure your approach is appropriate?
I am not very familiar with MYSQL but I think you DELETE and INSERT should come after Cursor declaration and and before opening and closing the cursor.
Is it possible to use a procedure inside a function? For example, I would like to gather all my rows related to an id but I would also like to count the rows and use it in a select statement. This is not working:
drop procedure if exists relatives;
create procedure relatives(in parent int(11),out counted int(11))
begin
set counted=(select count(*) from category where related=parent);
end;
drop function if exists relatives_count;
create function relatives_count(parent parent(11)) returns int(11)
begin
declare count int(11);
call relatives(parent,counted);
return counted;
end;
So that I can use the count
select relatives_count(id) from category
This is just for curiosity purposes. It may look senseless since I can just call a single select query and get the same results but I want to know how I can use my procedure out variable in a function.
Yes, a MySQL FUNCTION can call a MySQL PROCEDURE.
But... the operations the procedure performs will be limited to the operations allowed by a function. (We can't use a procedure to workaround the limitations placed on a function.)
"is not working" is so nebulously vague as to be practically useless in debugging the issue. What exact behavior is being observed?
My suspicion is that the SQL statements shown are failing, because there is no override for the default statement delimiter.
Also, parent(11) is not a valid datatype.
Be aware that when an identifier for a column in a SQL statement in a MySQL stored program matches an identifier used for an argument or local variable, MySQL follows a rule about which (the column name or the variable) that is being referenced.
Best practice is to adopt a naming convention for arguments and local variables that do not match column names, and to qualify all column references with a table name or table alias.
Personally, I use a prefix for arguments and local variables (a for argument, l for local, followed by a datatype i for integer, d for date/datetime, n for decimal, ...
DELIMITER $$
DROP PROCEDURE IF EXISTS relatives$$
CREATE PROCEDURE relatives(IN ai_parent INT(11),OUT ai_counted INT(11))
BEGIN
SELECT COUNT(*)
INTO ai_counted
FROM category c
WHERE c.related = ai_parent
;
END$$
DROP FUNCTION IF EXISTS relatives_count$$
CREATE FUNCTION relatives_count(ai_parent INT(11))
RETURNS INT(11)
BEGIN
DECLARE li_counted INT(11);
CALL relatives(ai_parent,li_counted);
RETURN li_counted;
END$$
DELIMITER ;
Please identify the exact behavior you observe. Error message when creating the procedure? Error message when executing the function? Unexpected behavior. That's much more precise and informative than telling us something "is not working".
I am trying to write a function that looks for a value assigned to its configuration in a parent-child tree, if the value is null or empty it looks one level up for the value.
I am currently getting syntax errors when trying to create the function.
This is what i have so far,
DELIMITER //
CREATE FUNCTION `db`.`Configuration`(
`ColumnName` VARCHAR(128),
`CID` INT
)
RETURNS VARCHAR(256)
NOT DETERMINISTIC
BEGIN
DECLARE Config VARCHAR(256) DEFAULT NULL;
DECLARE Parent INT;
WHILE (#Config IS NULL OR #Config = "") DO
SELECT #ColumnName INTO #Config, `ParentID` INTO #Parent FROM `Table` WHERE `ID`=#CID;
END WHILE;
RETURN CONCAT(#Config, '::', #Parent);
END ;
//
DELIMITER ;
I am getting the following error when I try to add the function:
1327 - Undeclared variable: ParentID
Any help would be greatly appreciated!
You receive the error message in the question because you have multiple into clauses, whereas according to mysql manual on select ... into ... you can only have one. So, to get rid of this specific error message you nee to rewrite your select statement as:
SELECT #ColumnName, `ParentID` INTO #Config, #Parent FROM `Table` WHERE `ID`=#CID;
However, there are some further issues with your code:
varname and #varname do not refer to the same variable. The first one is either a function / stored proc parameter or local variable, while the 2nd one is a user-defined variable. In your code you must remove the # from the variable names.
You cannot use a variable in place of a field name in an sql statement. You must use dynamic sql with prepared statements to achieve this. See the following SO question on how to this: How To have Dynamic SQL in MySQL Stored Procedure
You do not overwrite CID parameter in your while loop. This means that if the first iteration the configuration will remain null, then you have an infinite loop. You should change the value of CID in your loop.
I cannot guarantee that there are no further errors in your code.
There are a few problems with your function:
You are using SELECT...INTO incorrectly. When selecting multiple values you should only use INTO once. For example SELECT a,b into #a,#b FROM...
You are using user-defined variables with similar names to your function parameters, but they are not the same thing. In your code CID and #CID are different. I suggest using standard naming prefixes to clarify this: for example use p_ for function parameters and v_ for local function variables. You shouldn't need to use user-defined variables at all.
Your WHILE loop is bound to lead to infinite loops since the query criteria never changes. If it returns NULL or empty string once, it will keep returning them forever.
Here's a quick rewrite to address the above issues. I'll leave it to you to implement the WHILE loop correctly:
DELIMITER //
CREATE FUNCTION `db`.`Configuration`(
p_column_name VARCHAR(128),
p_id INT
)
RETURNS VARCHAR(256)
READS SQL DATA
BEGIN
DECLARE v_config VARCHAR(256) DEFAULT NULL;
DECLARE v_parent INT;
SELECT p_column_name,`ParentID`
INTO v_config, v_parent
FROM `Table`
WHERE `ID`=p_id;
RETURN CONCAT(v_config, '::', v_parent);
END ;
//
DELIMITER ;
I try to understand how functions work. I can make the equivalent in procedure but I can't create a simple function with select.
element is UNIQUE and
thing is PRIMARY
CREATE DEFINER=`root`#`localhost`
FUNCTION `get_element_by_thing`(`thing` VARCHAR(255))
RETURNS VARCHAR(255)
CHARSET utf8
NOT DETERMINISTIC
READS SQL DATA
SQL SECURITY DEFINER
DECLARE #return_element VARCHAR(255);
SET #return_element = (
SELECT
`element`
FROM
`table1`
WHERE
`thing` = thing
);
RETURN #return_element;
I use the phpmyadmin interface.
1) Don't declare user-defined variables.
The name of a local variable in MySQL stored program does not start with an at sign #. As an example:
DECLARE stored_program_local_variable VARCHAR(255);
SET stored_program_local_variable = 'somevalue';
The name of a user-defined variables start with an at sign #. (The at sign character is what distinguishes user-defined variables from other identifiers.) It's not valid to declare a user-defined variable in a stored program. To create a user-defined variable, just assign a value to it. For example:
SET #user_defined_variable = 'somevalue';
2) If we don't need to persist variables beyond the scope of a stored program, we typically use local variables, which exist only for the duration of the stored program execution. (Which is different behavior than user-defined variables which are at the session level.)
3) Use the SELECT ... INTO syntax to retrieve scalar values into user-defined or local variables. https://dev.mysql.com/doc/refman/5.7/en/select-into.html
Try:
DELIMITER $$
CREATE DEFINER=`root`#`localhost`
FUNCTION `get_element_by_thing`(`thing` VARCHAR(255))
RETURNS VARCHAR(255)
...
BEGIN
DECLARE return_element VARCHAR(255) ;
SELECT t1.element
INTO return_element
FROM table1 t1
WHERE t1.thing = thing
LIMIT 1 ;
RETURN return_element ;
END $$
DELIMITER ;
Note: with ambiguous identifiers (i.e. routine parameter and column with the same name in a SQL statement, the routine parameter takes precedence over the column name. Qualify the column reference with the table name or table alias so it's not ambiguous. I prefer to assign routine parameters (and local variables) names that do not match column names.
If for some reason you need to assign a value to a user-defined variable in a SQL statement, you can use the := assignment operator. This is also valid outside the context of a stored program.
SELECT #user_defined_variable := t.somecolumn
FROM mytable t
WHERE somecondition
ORDER BY someexpression
LIMIT 1
I am trying to create a user-defined function in MySQL in order to generate unique numbers. As the auto_increment feature of MySQL just increments its seed by one, I need to have such a function to handle fields that need to be incremented by more than one. Here is my SQL script:
DELIMITER $$
CREATE FUNCTION `getUniqueID`(
id_type CHAR(1)
) RETURNS INT(10)
BEGIN
DECLARE run INT(10);
START TRANSACTION;
SELECT unique_gen_id INTO #run FROM tbl_unique_seed WHERE id_type = #id_type;
UPDATE tbl_unique_seed SET unique_gen_id = (unique_gen_id + 1) WHERE id_type = #id_type;
COMMIT;
RETURN run;
END$$
DELIMITER ;
I do not have much experience in MySQL, but creating this kind of functions in SQL Server is quite easy. It will be nice of you to help me figure out a solution for this issue. Currently, I am facing some syntax errors. The most basic ones relate to the syntax of my transaction and the select statement.
See the docs here: http://dev.mysql.com/doc/refman/5.0/en/replication-options-master.html#sysvar_auto_increment_increment
You can change the value of auto_increment_increment, which is normally 1.