MySql update. difference between procedure results and phpmyadmin sql - mysql

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.

Related

MySQL Stored Procedure Variable as Table Name concatenated

I have the following query I want to execute in my stored procedure WITHOUT PREPARING the query, since this gives me problems with OUT to pass back parameters.
DELIMITER //
CREATE PROCEDURE Test (
IN CID BIGINT(20),
IN IDs LONGTEXT
)
BEGIN
#EXECUTE UNDERNEATH QUERY
SELECT * FROM CONCAT('Part1_OfTableName', CID); #CID IS CustomerID
END //
DELIMITER ;
However, this fails and I don't know how to fix the problem.
(Note that in the example I have no spaces in my table name, however in my situation I might have a space in my table name though)
PREPARE should have no bearing on your ability to successfully set OUT parameters of your procedure
SET DELIMITER //
CREATE PROCEDURE test(IN cid INT, IN ids TEXT, OUT out_int INT)
BEGIN
SET #sql = CONCAT('SELECT * FROM `table_', cid, '`', CASE WHEN ids IS NULL THEN '' ELSE CONCAT(' WHERE id IN( ', ids, ')') END);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET out_int = 1;
END//
SET DELIMITER ;
Sample usage:
mysql> CALL test(1, '2,3', #out_int);
+------+
| id |
+------+
| 2 |
| 3 |
+------+
2 rows in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT #out_int;
+----------+
| #out_int |
+----------+
| 1 |
+----------+
1 row in set (0.00 sec)
If you need to return results from a stored procedure using sql statement that must be prepared, you can use an intermediate temp table.
BEGIN
CREATE TEMPORARY TABLE `myresults` blah blah....;
//construct and prepare select you would've used, but start it with an insert like so...
// INSERT INTO `myresults` SELECT ....
// Execute the prepared query
SELECT * FROM `myresults`;
DROP TEMPORARY TABLE `myresults`;
END
...at least I am pretty sure this technique used to work; I've been working more in MSSQL the last couple years.
Something to note:
Temporary tables are connection/session specific, so while safe from a global perspective using a generic name like myresults can be problematic if queries executed earlier on the connection/session (or by a procedure calling this one) use the same name; in practice/paranoia, I tended to use a different guid (in each procedure using this technique) as a prefix for any temporary tables generated within it.

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

MySQL, create a simple function [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I want to create a simple MySQL function, I have this MySQL procedure:
CREATE PROCEDURE getUser(gU INT)
SELECT * FROM Company
WHERE id_number = gU;
CALL getUser(2);
I need some help making this into a MySQL function. What are the pros and cons of using a function over a procedure?
this is a mysql function example. I hope it helps. (I have not tested it yet, but should work)
DROP FUNCTION IF EXISTS F_TEST //
CREATE FUNCTION F_TEST(PID INT) RETURNS VARCHAR
BEGIN
/*DECLARE VALUES YOU MAY NEED, EXAMPLE:
DECLARE NOM_VAR1 DATATYPE [DEFAULT] VALUE;
*/
DECLARE NAME_FOUND VARCHAR DEFAULT "";
SELECT EMPLOYEE_NAME INTO NAME_FOUND FROM TABLE_NAME WHERE ID = PID;
RETURN NAME_FOUND;
END;//
MySQL function example:
Open the mysql terminal:
el#apollo:~$ mysql -u root -pthepassword yourdb
mysql>
Drop the function if it already exists
mysql> drop function if exists myfunc;
Query OK, 0 rows affected, 1 warning (0.00 sec)
Create the function
mysql> create function hello(id INT)
-> returns CHAR(50)
-> return 'foobar';
Query OK, 0 rows affected (0.01 sec)
Create a simple table to test it out with
mysql> create table yar (id INT);
Query OK, 0 rows affected (0.07 sec)
Insert three values into the table yar
mysql> insert into yar values(5), (7), (9);
Query OK, 3 rows affected (0.04 sec)
Records: 3 Duplicates: 0 Warnings: 0
Select all the values from yar, run our function hello each time:
mysql> select id, hello(5) from yar;
+------+----------+
| id | hello(5) |
+------+----------+
| 5 | foobar |
| 7 | foobar |
| 9 | foobar |
+------+----------+
3 rows in set (0.01 sec)
Verbalize and internalize what just happened:
You created a function called hello which takes one parameter. The parameter is ignored and returns a CHAR(50) containing the value 'foobar'. You created a table called yar and added three rows to it. The select statement runs the function hello(5) for each row returned by yar.
Try to change CREATE FUNCTION F_TEST(PID INT) RETURNS VARCHAR this portion to
CREATE FUNCTION F_TEST(PID INT) RETURNS TEXT
and change the following line too.
DECLARE NAME_FOUND TEXT DEFAULT "";
It should work.

How can I select out parameters in a MySQL procedure as table columns?

Environment: MySQL 5.1, Linux
I have a stored procedure that computes several values from a single input value. The values are returned as OUT parameters. I would like to call this procedure for every row set and have the values appear as columns in the result set. The values have a complex relationship such that distinct functions for each value is not easily constructed.
The question: How can I get OUT parameters to show up as columns in a table?
Here's what I have so far:
DELIMITER $_$
DROP PROCEDURE IF EXISTS in_out;
CREATE PROCEDURE in_out (
IN s TEXT,
OUT op TEXT,
OUT opn INT,
OUT opd TEXT,
OUT len INT
)
BEGIN
SET op = 'del';
SET opn = 1;
SET opd = substr(s,4);
SET len = LENGTH(SUBSTR(s,4));
END
$_$
DELIMITER ;
Then:
mysql> call in_out('delACT',#op,#opn,#opd,#len);
Query OK, 0 rows affected (0.00 sec)
mysql> select #op,#opn,#opd,#len;
+------+------+------+------+
| #op | #opn | #opd | #len |
+------+------+------+------+
| snv | 1 | ACT | 3 |
+------+------+------+------+
1 row in set (0.00 sec)
So far so good, but I can't figure out how to call this procedure for every row and return the results in the result set. I want is something like this:
dream> select mycol,in_out(mycol) from mytable
+---------+------+------+------+------+
| mycol | #op | #opn | #opd | #len |
+---------+------+------+------+------+
| delACT | del | 1 | ACT | 3 |
+---------+------+------+------+------+
Thanks!
You confuse the stored procedures and stored functions:
stored function will be return a value, the results can be used in
expressions (like COS() and other mysql built-in functions).
stored procedure need use CALL , is an independent operation, can not
be used in expressions.
If you want to "select mycol,in_out(mycol) from mytable",you must:
CREATE FUNCTION in_out( ...
This appears to be a trick question: one can't create table relations out of function/procedure results in MySQL. I ended up refactoring into separate functions (as suggested by MichaƂ). I had been hoping for a MySQL equivalent to PostgreSQL's table functions (http://goo.gl/77QVE).
I'd recommend to prepare data in stored procedure for each possible value in:
select distinct mycol
from mytable
where <... condition that you would use anyway in final result ...>
where mycol is your parameter for stored procedure save it to temporary table and than join to this values.
-- way the temp table may look in your sp
create temporary table tmptable (
mycol text
op text,
opn int,
opd text,
len int
)
after that use join:
select m.mycol, t.op, t.opn, t.opd, t.len
from mytable m
join tmptable t on m.mycol = t.mycol
where <... condition that you would use anyway in final result ...>
Bit different question, are you absolutely sure that there is no different way to process your final result than using a stored procedure?

MySQL Non-Negative INT Columns

I want to do the following query:
UPDATE `users` SET balance = (balance - 10) WHERE id=1
But if the balance will become a negative number I want an error to be returned. Any ideas on if this is possible?
If you do
UPDATE `users` SET balance = (balance - 10) WHERE id=1 and balance >=10
You should be able to detect that a row was not modified.
Note that while another answer suggests using an unsigned int column, this may not work:
Create a test table
create table foo(val int unsigned default '0');
insert into foo(val) values(5);
Now we attempt to subtract 10 from our test row:
update foo set val=val-10;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 1
mysql> select * from foo;
+------------+
| val |
+------------+
| 4294967295 |
+------------+
This was on mysql 5.0.38
You can make the balance field of the users table an unsigned int:
ALTER TABLE `users` CHANGE `balance` `balance` INT UNSIGNED;
This sort of things is done by triggers. MySql have support for triggers only since 5.0.2.
DELIMITER $$
CREATE TRIGGER balance_check BEFORE INSERT ON user FOR EACH ROW
BEGIN
IF new.balance < #limit_value THEN
-- do something that causes error.
-- mysql doesn't have mechanism to block action by itself
END IF;
END $$
DELIMITER ;
Triggers in MySql are quite rudimentary. You have to hack things around to do some things (e.g. cause error).
I dont think you can do this with a simple query. you should use a mysql user defined function that manage that before update the row. or a trigger
Just a tip that wouldn't fit as a comment. I was just trying to subtract 32000 from 32047 (not a negative result) and was getting errors. Also confusing, I was getting BIGINT errors but my subtraction was on a SMALLINT column! (Which still makes no sense.)
If you're getting "out of range" errors even when your "balance" is positive, try adding "limit 1" to the end of your query. Maybe this is a bug in MySQL?
mysql> update posts set cat_id=cat_id-32000 where timestamp=1360870280;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(`xxxxx`.`posts`.`cat_id` - 32000)'
mysql> update posts set cat_id=cat_id-32000 where timestamp=1360870280 limit 1;
Query OK, 1 row affected (6.45 sec)
Rows matched: 1 Changed: 1 Warnings: 0
In my case the timestamp is unique (I just checked to be sure) but not explicitly defined as unique when I created the table. So why is the "limit 1" here necessary? But who cares, it works!