If a local variable has the same name as an argument, the argument is overridden (shadowed). If the local variable is not initialized it will be NULL, regardless of the value passed through the argument. I had a procedure with that situation (below) and there was no warning or error. Is there some setting that will give warnings or errors if variables are shadowed?
CREATE DEFINER=`dev`#`localhost` PROCEDURE `new_empErrShadow`(in idVar int)
BEGIN
DECLARE idVar INT; -- ERROR shadows arg idVar, get null value (name conflict)
insert into Employees values (idVar, 28, 'ttt', 'lastname');
-- try get warning about variable shadow. Doesn't work
show errors;
show warnings;
END
Using MySQL 5.7 but 8.0 is the same according to documentation.
Name Conflicts within Stored Routines in
MySQL :: MySQL 5.7 Reference Manual :: 23.8 Restrictions on Stored Programs
I would recommend that you use consistent naming conventions instead:
CREATE DEFINER=`dev`#`localhost` PROCEDURE `new_empErrShadow` (
in in_idVar int
)
BEGIN
DECLARE p_idVar INT; -- ERROR shadows arg idVar, get null value (name conflict)
insert into Employees values (in_idVar, 28, 'ttt', 'lastname');
-- try get warning about variable shadow. Doesn't work
show errors;
show warnings;
END;
Such consistency will help you prevent the errors yourself.
Related
I have a problem with the following query:
START TRANSACTION;
INSERT INTO posts
(
-- not relevant
)
VALUES
(
-- insert works as intended
);
COMMIT WORK AND CHAIN;
DECLARE #insertId INT; -- this is where i get the syntax error
SET #insertId = LAST_INSERT_ID();
UPDATE posts
SET guid = CONCAT('foo.bar?p=', #insertId)
WHERE id = #insertId;
-- continue to work with the variable
INSERT INTO postmeta(post_id, key, value)
VALUES
(#insertId, ..., ...),
(#insertId, ..., ...),
(#insertId, ..., ...),
(#insertId, ..., ...);
COMMIT WORK;
Basically I insert a row, and need to update it, using the auto incremented id immediately after the insert (to make sure I get the correct value out of the function LAST_INSERT_ID).
Then I need to fill an other table, also using the auto incremented id. In this use case I figured, that I need to store the value in a variable.
Why do i get the following error message?
"You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'DECLARE #insertId INT; SET #insertId = LAST_INSERT_ID();' at line 1"
Is the problem that I don't create a procedure or user defined function?
I did a quick search and found this on the MariaDB website (https://mariadb.com/kb/en/user-defined-variables/):
"Since user-defined variables type cannot be declared, the only way to force their type is using CAST() or CONVERT()"
I think the solution is just removing the declare statement since there are examples on their site making variables without declaring them.
I hope this works, I'm not really familiar with MariaDB!
Why does the use of the assignment operator := fail to parse in this stored procedure (fragment)? In the update statement, in the set median = [select expression], in the expression, the MySQL 5.6 parser reports the error, "[Check]...for the right syntax to use near ':= row + 1 as row, $vol as $vol from univ_members' ".
delimiter //
CREATE PROCEDURE m()
BEGIN
DECLARE row int;
SELECT row := row + 1 AS row;
END //
delimiter ;
Running the select statement the mysql shell also fails, but says, 'row' is not a system variable or 'row' is not a column, depending on whether I try to define it with 'set'.
Do you know of a limitation in a stored procedure that prohibits this, or of such a bug in MySQL 5.6? If so, is there a workaround? Can you suggest an alternative approach?
So, after struggling like a man blinded by darkness, I defined the variable #row in the shell using 'set' (the shell's parser does not allow 'row') and it worked. The parser however does not allow a variable defined in a stored procedure with 'declare' to begin with a '#', but, if defined with 'set', it works, it does allow it to be used as the left-hand value in the :=.
So, it's an issue with variable definition. Evidently, only 'user variables', which must begin with a '#' and must be defined with 'set', can be assigned values with ':='. (See User-Defined Variables)
I find such a nuance that all variables don't share a common behavior when it comes to assignment non-intuitive and incredibly irritating. Am I still missing something?
I have a simple custom type for use it as table valued parameter.
Like this:
CREATE TYPE dbo.PeriodsList AS TABLE
(
PeriodDate NVARCHAR(8) NOT NULL
)
I also have very simple table valued function:
alter FUNCTION GetPeriodsInYear (#periods dbo.PeriodsList READONLY) returns #PeriodsSet Table(period NVARCHAR(8))
BEGIN
insert #PeriodsSet
select
'0' as period
Return
end
But when I try to execute this function in this way
DECLARE #periods1 dbo.PeriodsList
INSERT INTO #periods1
VALUES ('20130916')
select * from GetPurchasesInYear(#periods1)
I receive error message - "Must declare the scalar variable "#periods1".
I have found many examples about stored procedures but not about functions. Is it possible to pass table valued parameters into functions?
And where the mistake in my code?
Check the "compatibility level" of your SQL Server 2008 database. If it's set to 80 (SQL Server 2000), you will get the error you are describing when you try to call a function (but not a stored procedure) that takes a table-valued parameter.
It should work if the compatibility level value is 90 (SQL Server 2005) or higher.
To view the compatibility level of your database, do:
SELECT compatibility_level
FROM sys.databases
WHERE name = 'YOUR_DB_NAME_HERE';
Source: http://msgroups.net/microsoft.public.sqlserver.programming/pass-table-valued-para/97879
Changing the compatibility level (SQL Server 2008): http://technet.microsoft.com/en-us/library/bb510680%28v=sql.100%29.aspx
I am having difficulty establishing the correct syntax for calling a stored procedure within a stored procedure. I thought this syntax was correct:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[newProc](
#param1 varchar(50),
#param2 nvarchar(2000),
#param3 int,
#param4 int,
#param5 int,
#param6 int
)
AS
BEGIN
SET NOCOUNT ON;
EXEC [dbo].[externProc1] #param1, #param2;
GO
EXEC [dbo].[externProc2] #param3, #param4;
GO
EXEC [dbo].[insertProc3] #param5, #param6;
GO
END
GO
But when I try this, I keep getting
"Incorrect syntax near ';' Must declare the scalar variable #param3.
Must declare the scalar variable #param5."
What is the correct syntax for calling a stored procedure with parameters from within another stored procedure?
The GO keyword in T-SQL states that a block of t-sql statements ends and executes that block. This means that a variable defined in one block is not longer "in scope" for a statement occurring after that block has been ended/executed with GO.
GO is not actually a transact sql statement:
http://msdn.microsoft.com/en-us/library/ms188037(v=sql.105).aspx
Users must follow the rules for batches. For example, any execution of
a stored procedure after the first statement in a batch must include
the EXECUTE keyword. The scope of local (user-defined) variables is
limited to a batch, and cannot be referenced after a GO command.
In MySQL 5, a stored procedure can return any number of output parameters, like this:
CREATE PROCEDURE `test1`(IN in1 VARCHAR(64), IN in2, OUT out1 VARCHAR(64), OUT out2 INT, OUT out3 INT)
In MySQL 5, a stored procedure can also return/print a resultset, like this:
CREATE PROCEDURE `test2` ()
BEGIN
SELECT * FROM `table`;
END$$
This is nice and flexible. So in trying to communicate with the outside world, what's the convention for using this flexibility to give notice of the results (if any) and the errors (if any)?
Examples:
Do we put error messages in our output parameters? Do we put them in resultsets?
Do we print out multiple successive resultsets? Or do we limit ourselves to one resultset?
Do we set the resultset to NULL if there are errors?
Do we use output paramenter integers for the errors, with 0 being error free?
Do we use output parameter VARCHARs for the errors, with '' (empty string) meaning error free?
I think it makes sense to use Signals for returning an error if it's supported by the server (5.5 and up).