MySQL Stored procedure with local variable not working in LINUX - mysql

I'm struggling with a simple stored procedure, that I've reduced to this:
CREATE PROCEDURE RemoveDuplicateModules()
BEGIN
SET #myvar=1;
End;
When I run this in the MySQL CLI I get: parameter #myvar has not been created. I'm struggling cause in windows it works fine!
mysql --version = 5.6.33

Works for me (debian, mysql 5.6.25):
mysql> delimiter //
mysql> CREATE PROCEDURE RemoveDuplicateModules()
-> BEGIN
-> SET #myvar=1;
-> End;
-> //
Query OK, 0 rows affected (0,66 sec)
mysql> call RemoveDuplicateModules();
Query OK, 0 rows affected (0,00 sec)
mysql> select #myvar ;
+--------+
| #myvar |
+--------+
| 1 |
+--------+
1 row in set (0,02 sec)

Seems that the problem here was not that the procedure I posted was failing, but since it was being executed in a larger context, a big file with a lot of code from a lot of people, a previous lack of a commit made my procedure to fail. Anyway, thanks for the help!

Related

difference on times procedure execution in mysql console

When I execute a mysql procedure on the console, this always show two times but I don't know what time each thing refers to.
Thanks in advance!
Your procedure must do a SELECT followed by some non-SELECT.
Here's a demo:
mysql> delimiter ;;
mysql> create procedure p() begin select 123; do 123+456; end;;
mysql> delimiter ;
mysql> call p;
+-----+
| 123 |
+-----+
| 123 |
+-----+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
The two times reported are for the two SQL statements run in the procedure.
The first statement returned a row.
The second statement did not return a row, but still had to execute, therefore it reported its time.
Statements that have a result set include SELECT and SHOW.
All other statements have no result set, but may affect rows. Like if an UPDATE changes rows, it will report it affected some number of rows, which are the rows it changed.
The quick example I showed in my demo only uses the DO statement, which evaluates an expression but doesn't change any data or return any data.

MySql update. difference between procedure results and phpmyadmin sql

I am having difficult getting a procedure to update a table in the way I require. I am using phpmyadmin on my local computer. In phpmyadmin I can put the following code into the SQL tab and one row will be updated:
SET `adjCost` = 22.05 WHERE `Name` LIKE CONCAT('magic', '%') AND `idKey` = '2016fulham02345';
As expected and wanted, IF the name begins with magic AND the idKey is '2016fulham02345' THEN the adjCost is updated to 22.05.
There will be between 2 and 50 rows with the same idKey. The Name will never be repeated in a set with the same idKey.
I created a procedure with the following parameters:
IN idK VARCHAR 255 Charset
IN aName VARCHAR 255 Charset
IN cost FLOAT 5,2
BEGIN
UPDATE `raceresults` SET `adjCost` = cost WHERE `Name` LIKE CONCAT(aName, '%') AND `idKey` = idK;
END
When I run this procedure it updates ALL adjCost where the idKey = idk and (seems) to ignore the name parameter.
I have tried concatenating the name string first:
BEGIN
SELECT CONCAT(aName, '%') INTO #str;
UPDATE `raceresults` SET `adjCost` = cost WHERE `Name` = #str AND `idKey` = idK;
END
but to no avail.
I looked through w3schools, stackoverflow and google and have not been able to find the answer.
My question is:
How can I correct my procedure to get it to work as I would like?
UPDATE: as requested.
CREATE DEFINER=`root`#`localhost` PROCEDURE `importAltUpdateAjdCost`(IN `idK` VARCHAR(255), IN `aName` VARCHAR(255), IN `cost` FLOAT(5,2))
NO SQL
BEGIN
UPDATE `costingPP`
SET `adjCost` = cost
WHERE
`Name` LIKE CONCAT(aName, '%')
AND
`idKey` = idK;
END
To get this, I selected export on my list of procedures on phpmyadmin.
I'm not entirely sure what or how you did, but here's what I did and it instantly worked. Since you didn't specify MySQL version, I used 5.7.
EDIT: Now as I went back to see your procedure creation statement I realised that NO SQL was introduced in MySQL 8.0. Since your procedure clearly is SQL then please remove the NO SQL and re-create the procedure.
I'm leaving my MySQL 5.7 sample here for reference:
1) Created a simple table:
mysql> CREATE TABLE raceresults (
-> idKey VARCHAR(255),
-> Name VARCHAR(255),
-> adjCost FLOAT(5,2)
-> );
Query OK, 0 rows affected (0.06 sec)
2) Here we insert a sample data row:
mysql> INSERT INTO raceresults VALUES ('2016fulham02345', 'magicFlyingHorse', 0.00);
Query OK, 1 row affected (0.01 sec)
3) To create a (STORED) PROCEDURE we have to temporarily set a different delimiter, so query parser wouldn't terminate procedure creation on default semi-colon, as it's used inside the procedure. After delimiter's change we create the procedure and set the delimiter back to semi-colon
mysql> DELIMITER //
mysql> CREATE PROCEDURE update_test(IN idK VARCHAR(255), IN aName VARCHAR(255), IN cost FLOAT(5,2))
-> BEGIN
-> UPDATE `raceresults` SET `adjCost` = cost WHERE `Name` LIKE CONCAT(aName, '%') AND `idKey` = idK;
-> END//
mysql> DELIMITER ;
Query OK, 0 rows affected (0.00 sec)
4) Now let's see how it all works. Before and after the procedure call I'm selecting the rows from database. You can see the cost column value changing:
mysql> SELECT * FROM raceresults;
+-----------------+------------------+---------+
| idKey | Name | adjCost |
+-----------------+------------------+---------+
| 2016fulham02345 | magicFlyingHorse | 0.00 |
+-----------------+------------------+---------+
1 row in set (0.00 sec)
mysql> CALL update_test('2016fulham02345', 'magic', 1.23);
Query OK, 1 row affected (0.02 sec)
mysql> SELECT * FROM raceresults;
+-----------------+------------------+---------+
| idKey | Name | adjCost |
+-----------------+------------------+---------+
| 2016fulham02345 | magicFlyingHorse | 1.23 |
+-----------------+------------------+---------+
1 row in set (0.00 sec)
And now one piece of advise too:
If possible, use only lower case table, column, indexes, functions, procedures, etc... names, while always writing all SQL commands in uppercase (which you did). This is kind of a de facto standard and makes life easier both for you and others reading your code.

Dynamic SQL alternatives (MySql)

On current MySql DB server, i have two schemas: "Friends", "Places". Entire DB is organized around stored procedures which are being called from outside. Maybe it's good approach, maybe it's bad but it's not related to this problem i'm having. In this case DB has to be separated from any outside software using it (as i'm only in charge of DB).
Some stored procedures from "Friends" schema refer to tables from "Places" and vice versa. Now, if for example i wanna setup new set of schemas, on the same server, but for another "client" like this:
Friends_clientOne
Places_clientOne
Friends_clientTwo
Places_clientTwo
I'm having a problem - stored procedures referring tables from another schema won't know which schema name to use. Checking and modifying each and every procedure to suite appropriate schema name every time new set is created is not an option. Dynamic SQL is totally new for me - what are other options? How can i, for example, do this:
(stored procedure inside schema Friends_clientOne):
Select * from Places_<getCurrentSchemaSuffix>.someTable;
Please tell me MySql is flexible enough for this :( What about Percona?
The closest thing to what you're describing is a builtin function DATABASE() (http://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_database), which returns the current default database.
The default database isn't necessarily the one that a given table belongs to. It's the database most recently named in a USE <databasename> statement. If you can rely on your application always using the database you mean for that table to belong to, then you can use that function.
However, no SQL implementation allows you to change the table name dynamically during query execution. You can name tables only before doing the prepare of a statement, and hard-coding it into the query. There is no syntax for making the table name variable.
So you'll have to use dynamic SQL even if you use the DATABASE() function.
Percona Server is no different from stock Oracle MySQL for this problem.
Your options for this problem are:
Stop using multiple schemas for each client. Put all of the data for each client into a single schema. This seems simplest.
Design the stored procedures to be unique to each client. You said you didn't want to do this. But for what it's worth, we do this in the stored procedures and triggers in the customer databases I manage at my current job. It's not that bad. We have a "template" version of the CREATE statements for each trigger or procedure, with a placeholder token for the customer ID. When we create a new customer's database, we copy that template code and make a substitution on the customer ID placeholder, then run it.
Put each of your clients' data into their own exclusive instance of MySQL Server. This way you can have multiple schemas per client, but the schema names don't need to be distinct for each client. You can run multiple instances on one server host, they just have to be configured with distinct datadir, port, sock_file, and other log files. Though I have seen this solution used, I don't recommend it, because it has a lot of resource overhead, and it's hard to manage.
Learn to use dynamic SQL.
You can use PREPARED Statement in the Procs like this:
DELIMITER //
CREATE PROCEDURE getPlace (OUT param1 char)
BEGIN
SELECT CONCAT("Select * from Places_", SUBSTRING_INDEX(DATABASE(), '_', -1),".someTable;") INTO #sql;
PREPARE getPlaces from #sql;
EXECUTE getPlaces;
DEALLOCATE PREPARE getPlaces;
END;
//
DELIMITER ;
sample
MariaDB [mysql]> CREATE DATABASE Friends_clientOne;
Query OK, 1 row affected (0.00 sec)
MariaDB [mysql]> CREATE DATABASE Friends_clientTwo;
Query OK, 1 row affected (0.00 sec)
MariaDB [mysql]> CREATE DATABASE Places_clientOne;
Query OK, 1 row affected (0.00 sec)
MariaDB [mysql]> CREATE DATABASE Places_clientTWO;
Query OK, 1 row affected (0.00 sec)
MariaDB [mysql]> CREATE TABLE Places_clientOne.someTable (name varchar(32));
Query OK, 0 rows affected (0.02 sec)
MariaDB [mysql]> CREATE TABLE Places_clientTwo.someTable (name varchar(32));
Query OK, 0 rows affected (0.02 sec)
MariaDB [mysql]> INSERT INTO Places_clientOne.someTable VALUES('text in Places_clientOne.someTable');
Query OK, 1 row affected, 1 warning (0.00 sec)
MariaDB [mysql]> INSERT INTO Places_clientTwo.someTable VALUES('text in Places_clientTwo.someTable');
Query OK, 1 row affected, 1 warning (0.01 sec)
MariaDB [mysql]> use Friends_clientOne;
Database changed
MariaDB [Friends_clientOne]> DELIMITER //
MariaDB [Friends_clientOne]> CREATE PROCEDURE getPlace (OUT param1 char)
-> BEGIN
-> SELECT CONCAT("Select * from Places_", SUBSTRING_INDEX(DATABASE(), '_', -1),".someTable;") INTO #sql;
-> PREPARE getPlaces from #sql;
-> EXECUTE getPlaces;
-> DEALLOCATE PREPARE getPlaces;
-> END;
-> //
Query OK, 0 rows affected (0.03 sec)
MariaDB [Friends_clientOne]> DELIMITER ;
MariaDB [(none)]> use Friends_clientTwo;
Database changed
MariaDB [Friends_clientTwo]> DELIMITER //
MariaDB [Friends_clientTwo]>
MariaDB [Friends_clientTwo]> CREATE PROCEDURE getPlace (OUT param1 char)
-> BEGIN
-> SELECT CONCAT("Select * from Places_", SUBSTRING_INDEX(DATABASE(), '_', -1),".someTable;") INTO #sql;
-> PREPARE getPlaces from #sql;
-> EXECUTE getPlaces;
-> DEALLOCATE PREPARE getPlaces;
-> END;
-> //
Query OK, 0 rows affected (0.02 sec)
MariaDB [Friends_clientTwo]> DELIMITER ;
MariaDB [Friends_clientTwo]> call getPlace(#r);
+----------------------------------+
| name |
+----------------------------------+
| text in Places_clientTwo.someTab |
+----------------------------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
MariaDB [Friends_clientTwo]> use Friends_clientOne;
Database changed
MariaDB [Friends_clientOne]> call getPlace(#r);
+----------------------------------+
| name |
+----------------------------------+
| text in Places_clientOne.someTab |
+----------------------------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
MariaDB [Friends_clientOne]>

Temporary Table in Stored Procedure Not Found in MySQL

I've inherited some code that uses stored procedures and one of them doesn't appear to be working correctly.
The stored procedure uses a temporary table to insert data later in the procedure. However when I execute the stored procedure, no data is inserted. When I debug it, I get the error:
Table 'db.testtable' doesn't exist
I've stripped down the stored procedure to the following code, and it doesn't work. I always get the error on the SELECT statement. Everything looks OK from what I can tell based on the examples I've seen.
DROP PROCEDURE IF EXISTS db.insert_record;
CREATE PROCEDURE db.`insert_record`(id int, status int)
BEGIN
DECLARE code varchar(45);
DROP TEMPORARY TABLE IF EXISTS testTable;
CREATE TEMPORARY TABLE testTable AS (SELECT 'TEST' AS fakeColumn);
SELECT fakeColumn INTO code FROM testTable;
END;
I've also verified that the user I am connected as has the permission to create temporary tables; in fact it has every permission available
Additional Details
Running MySQL 5.6 on Windows.
If I take the drop / create / select statements by themselves and run as a script, it behaves as expected.
Using Toad for MySQL to debug the stored procedure.
I can't reproduce the problem. What other information can you provide?
mysql> USE `test`;
Database changed
mysql> SELECT VERSION();
+-----------------+
| VERSION() |
+-----------------+
| 5.5.22-0ubuntu1 |
+-----------------+
1 row in set (0.00 sec)
mysql> DELIMITER //
mysql> DROP PROCEDURE IF EXISTS `insert_record`//
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE PROCEDURE `insert_record`(`id` int, `status` int)
-> BEGIN
-> DECLARE `code` VARCHAR(45);
-> DROP TEMPORARY TABLE IF EXISTS `testTable`;
-> CREATE TEMPORARY TABLE `testTable` AS (SELECT 'TEST' AS `fakeColumn`);
-> SELECT `fakeColumn` INTO `code` FROM `testTable`;
-> SELECT `code`;
-> END//
Query OK, 0 rows affected (0.01 sec)
mysql> CALL `insert_record`(NULL, NULL)//
+--------+
| `code` |
+--------+
| TEST |
+--------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
SQL Fiddle demo

Update TIME mysql stored procedure

mySql :
Your SQL query has been executed successfully
0 rows affected by the last statement inside the procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `update_adm`(OUT `sp_out` INT(11), IN `sp_email` VARCHAR(50) CHARSET utf8)
NO SQL
BEGIN
UPDATE `admin` SET `last_try`=curtime() WHERE `email`=sp_email;
SET sp_out=ROW_COUNT();
END
why 0 rows affected by the last statement inside the procedure ?!
edited :
When I replace sp_email with correct value like navid#yahoo.com in my stored procedure, it works perfectly !
CREATE DEFINER=`root`#`localhost` PROCEDURE `update_adm`()
NO SQL
BEGIN
UPDATE `admin` SET `last_try`=curtime() WHERE `email`='navid#yahoo.com';
END
From the MySQL command line, the output is as expected.
mysql> delimiter $$
mysql> CREATE DEFINER=`root`#`localhost PROCEDURE update_adm( ...
-> END$$
Query OK, 0 rows affected (0.16 sec)
mysql> delimiter ;
mysql> insert into admin values (null,'foo');
Query OK, 1 row affected (0.00 sec)
mysql> call update_adm(#cnt,'foo');
Query OK, 1 row affected (0.00 sec)
mysql> call update_adm(#cnt,'bar');
Query OK, 0 rows affected (0.00 sec)
When I call the procedure with an email that exists, I get a message back showing 1 row was affected. When I call the procedure with an email that does exist, it returns a message back showing 0 rows affected.
I believe the message you are seeing is from the client interface. What client are you using to call the procedure?