MySQL Case Error 1111 - Max(Column) Case Statement in SP - mysql

Summary: I am trying to add a Username to the db.username_table with a unique ID incremented by 1. However, I keep receiving an error 1111 related to my CASE statement. It should make the first User_ID 1, then all other new ones the max(user_id) +1. Any help would be greatly appreciated!
Background: This is for my first MySQL project - I have some experience with MS SQL that may be hindering me here. I googled many references and streamlined my code as much as possible, but the aggregate for the counter returns a 1111 error with an IF or with a CASE statement.
DELIMITER $$
CREATE PROCEDURE db.add_user
(
in new_username varchar(45)
)
begin
-- Set Counter ID
declare new_user_id int;
set new_user_id = if(max(db.username_table.User_ID) is null, 1, max(db.username_table.User_ID) + 1);
-- Add Username with Counter
insert into db.username_table (user_id, username)
values (new_user_id, new_username);
END$$
DELIMITER ;
Expected Result - Add a Username to the db.username_table with a unique ID incremented by 1.
Actual Result - Error 1111.

You are using the funtion MAX but not in SQL statements .. so the max of is used improperly . you need a select for retrive a MAX(db.username_table.User_ID.)
declare new_user_id int;
select case when
max(ifnull(db.username_table.User_ID,0)) = 0
then 1
else max(db.username_table.User_ID) + 1 end
INTO new_user_id
from your_table ;
but could you simply need an autoincrement column for User_id and avoid this SP
CREATE TABLE your_table (
User_ID int(11) NOT NULL AUTO_INCREMENT,
....
)

Related

MySQL stored procedure UPDATE changing first row only

I have the following watching table
If I run this simple test query:
UPDATE
`watching`
SET
`lastPriceSeen` = 1.33
WHERE
`email` = 'blablanfff#gmail.com' AND
`productId` = 254857265
LIMIT 1
row ID 10 correctly updates to 1.33 in the lastPriceSeen column
If I convert this to a stored procedure:
DELIMITER ;;
CREATE PROCEDURE `updateLastSeenPrice`(
email VARCHAR(100),
productId INT(11),
price FLOAT
)
DETERMINISTIC
COMMENT 'Updates watcher last seen price'
BEGIN
UPDATE
`watching`
SET
`lastPriceSeen` = price
WHERE
`email` = email AND
`productId` = productId
LIMIT 1;
END;;
DELIMITER ;
and run CALL updateLastSeenPrice('blablanfff#gmail.com','254857265', 1.11)
Only the first row (ID 1) gets updated with the price, when I was expecting row ID 10 to update.
This makes no sense to me, the WHERE clause should prevent this from happening, and it's the same query! I've even added a SELECT at the end of the stored procedure to test it's receiving the IN parameters correctly and it is...
Any ideas as to why the first row gets updated? Why is it matching on that when the WHERE clause should prevent it from doing so?
The WHERE clause doesn't see the difference between the column name and parameter name. Therefore, any record will do and it will update the first one.
Change it into:
CREATE PROCEDURE `updateLastSeenPrice`(
p_email VARCHAR(100),
p_productId INT(11),
p_price FLOAT
)
DETERMINISTIC
COMMENT 'Updates watcher last seen price'
BEGIN
UPDATE
`watching`
SET
`lastPriceSeen` = p_price
WHERE
`email` = p_email AND
`productId` = p_productId
LIMIT 1;
END;;
DELIMITER ;

Get primary key column value of last inserted record in mysql

I would like to capture the primary key value of column based on the last inserted record. Below is the table structure:
create table test
(
id varchar(100) not null primary key,
rmain varchar(100),
rpart bigint
);
Stored Procedure:
Delimiter $$
DROP PROCEDURE IF EXISTS insTest$$
Create Procedure insTest()
Begin
Set #rmain := (select trim(concat('DNB', DATE_FORMAT(CURRENT_DATE(), '%y'), DATE_FORMAT(CURRENT_DATE(), '%m'))));
IF ((trim(DATE_FORMAT(CURRENT_DATE(),'%m')) = 01) OR (trim(DATE_FORMAT(CURRENT_DATE(),'%m')) = 1)) THEN
Set #rpart = 1;
END IF;
IF ((trim(DATE_FORMAT(CURRENT_DATE(),'%m')) != 01) OR (trim(DATE_FORMAT(CURRENT_DATE(),'%m')) != 1)) THEN
Set #rpart := (select coalesce(max(rpart),0) from test) + 1;
END IF;
insert into Test (ID, rmain, rpart) values (concat(#rmain,#rpart),#rmain,#rpart);
End$$
DELIMITER ;
Please advice. I checked on last_insert_ID() but it works for primary key column with auto_increment setting only. Thanks in advance...
Why? What if you get select max(id) or if you get select id from tbl1 order by id desc limit 1?
See Transaction In MySQL. Also, set the transaction isolation level to READ COMMITTED
declare last_id INT;
START TRANSACTION;
INSERT INTO tbl1(id,col1,col2) values(1001,'test','test');
SELECT last_id = id FROM tbl1 ORDER BY id DESC LIMIT 1
COMMIT;
INSERT INTO test (a,b,c) values (1,2,3);
SELECT LAST_INSERT_ID();
this way you can access the last inserted id

MySQL : Stored procedure returns null for last_insert_id

I'm facing a problem with SP in mySql when I want to select my identete it gives always null as value.
DELIMITER $$
CREATE PROCEDURE insert_details_facture(IN typefacture INT,
IN codeactivite VARCHAR(255),
IN qte INT,
IN pu DOUBLE,
IN unite VARCHAR(255),
IN montant DOUBLE)
BEGIN
DECLARE identete INT;
SELECT identete = numfacture FROM entetefacture WHERE numfacture = LAST_INSERT_ID();
END$$
When I execute this it gives identite = numfacture as column's name and null as value.
CALL insert_details_facture(10,'l',10,12,'l',20)
Check Here.
With no argument, LAST_INSERT_ID() returns a BIGINT UNSIGNED (64-bit) value representing the first automatically generated value successfully inserted for an AUTO_INCREMENT column as a result of the most recently executed INSERT statement.
so result you are getting is obvious.
to get last record you can use limit.
SET identete = (SELECT numfacture FROM entetefacture ORDER BY id DESC LIMIT 1);
LAST_INSERT_ID() is not guaranteed to have a valid value. For instance, the documentation states:
If the previous statement returned an error, the value of
LAST_INSERT_ID() is undefined. For transactional tables, if the
statement is rolled back due to an error, the value of
LAST_INSERT_ID() is left undefined.
Similarly, if there have been no database changes for the current session, then the value will be undefined.
Also, if you want to set the value, then use := in a select:
SELECT identete := numfacture
FROM entetefacture
WHERE numfacture = LAST_INSERT_ID();
Why not just get the last row in the table using limit?
SET identete = (SELECT numfacture FROM entetefacture ORDER BY id LIMIT 1);

MySQL - Update a column after information get's inserted

I have a table in MySql table like the following
row_timestamp timestamp
, row_id int(11) auto_increment
, mrn char(17)
, patients_last_name varchar(50)
, patients_first_name varchar(50)
, ssn char(4) default '0000'
, visit_key NULL
upon the insertion of a record, I'd like visit_key to bet set to visit_key = concat(mrn, row_id) I was trying to accomplish this with a before insert trigger to no avail, I kept getting that the mrn column was not in the field select list.
Update
I tried the following, which seems not to work because the auto_increment has not yet incremented:
set new.visit_key = concat(new.mrn, new.row_id)
I also tried
set new.visit_key = concat(new.mrn, max(row_id)+1)
I am thinking of the trigger to sort of act like a calculated field in MS Access, is this reasonable? Thoughts? Would it not be possible to do since the visit_key would technically be NULL and you cannot update a new value?
UPDATE
I used the following code that I adapted from this question here
DELIMITER //
CREATE TRIGGER vkt AFTER INSERT ON demographic_information
FOR EACH ROW
BEGIN
UPDATE `demographic_information` SET visit_key_test = concat(new.mrn, mew.row_id) WHERE row_id = NEW.row_id;
END;
//
DELIMITER ;
and got the following error message:
INSERT INTO `manchuco_nys_trauma`.`demographic_information` (
`row_timestamp` ,
`row_id` ,
`mrn` ,
`patients_last_name` ,
`patients_first_name` ,
`ssn` ,
`visit_id` ,
`visit_key_test`
)
VALUES (
CURRENT_TIMESTAMP , NULL , '123456', 'Sanderson', 'Steven', '1234', '12345670', NULL
)
MySQL said: Documentation
#1442 - Can't update table 'demographic_information' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
Thank you,
What you observe seems normal: since you're using BEFORE INSERT the id value doen't exist yet.
And the same applies for your try with concat(new.mrn, **new**.row_id): NEW has no sense at the moment.
So I suggest you use AFTER INSERT instead.
Try selecting the auto increment value inside the trigger:
CREATE TRIGGER trigger_name AFTER INSERT ON yourTable FOR EACH ROW
BEGIN
DECLARE next_id integer;
SET next_id = (SELECT AUTO_INCREMENT
FROM information_schema.TABLES
WHERE TABLE_SCHEMA='yourDB' AND TABLE_NAME='yourTable');
SET new.visit_key = CONCAT(new.mrn, next_id);
END
I discovered this approach in this SO article.

MySQL AUTO INCREMENT with Prefix (YYMM) that reset every month

I saw another post explaining the use of sequence table to create prefixed AUTO INCREMENT ID.
Link to referenced post
SQL Fiddle
http://sqlfiddle.com/#!2/0ed88/1
I need the generated auto increment format to be: YYMM + AUTO INCREMENT VALUE that reset every month. For example now is January, 2015. The generated id should be: 15011, 15012, 15013, etc. Next month February 2015, the generated id should be: 15021, 15022, 15023, etc. I can use the above method to generate the prefix, however how do I reset the AUTO INCREMENT value each month? Database is InnoDB. Any help will be greatly appreciated :)
MODIFIED CODE
CREATE TABLE table1_seq
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
)|
CREATE TABLE Table1
(
id VARCHAR(7) NOT NULL PRIMARY KEY DEFAULT '0', name VARCHAR(30)
)|
CREATE TRIGGER tg_table1_insert
BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
INSERT INTO table1_seq VALUES (NULL);
SET NEW.id = CONCAT(DATE_FORMAT(NOW(),'%y%m'), LAST_INSERT_ID());
END |
INSERT INTO Table1 (name) VALUES ('Jhon'), ('Mark')|
If you have a field DATE or DATETIME in your table then this solution maybe can help you.
Let say your table name my_table and has PK id (INT) and also a field bila (DATE). I just need to get last (biggest) id in current month from my_table then add by 1.
SET #mos= (SELECT MAX(id) FROM my_table WHERE MONTH(`bila`) = MONTH(NOW()) AND YEAR(`bila`) = YEAR(NOW()));
SET #mos = IF(
#mos IS NULL,
CONCAT(YEAR(NOW()),MONTH(NOW()),'001'),
#mos + 1
);
Then u can use #mos in your query next
To reset the AUTO_INCREMENT value, drop and recreate the table1_seq table. Given your example, a TRUNCATE statement would be sufficient (given that there aren't any foreign keys, and we assume the table is using either the MyISAM or InnoDB engine).
TRUNCATE TABLE table1_seq ;
(MySQL behavior for this statement is to create a new, empty table, with the AUTO_INCREMENT set back to the value when the table was created.)
This effectively achieves the same result as a DROP table followed by CREATE table.
That answers the question you asked. As a side note, generating a key value this way usually turns out to be a bad idea.
i've relied on the last answer above, i've used the orderDate field from my table and compared it with the current date during insertion , to decide finally if i want to reset or increment the purchaseOrderRef field:
The aim is to insert custom auto increment order id (field name: "purchaseOrderRef" ) with the format DD-MM-XXX in table [Products_SumOrders]. such that it resets the XXX to 0 automatically every month:
USE [Mydatabase] -- here you need to use your own database
GO
/****** Object: Trigger [dbo].[customAutoIncrement] Script Date: 10/1/2016 10:07:41 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[customAutoIncrement]
ON [dbo].[Products_SumOrders]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
declare #maxOrderID int;
declare #maxOrderRef nvarchar(max);
declare #relativeID varchar(max);
declare #orderId int;
select #orderId =orderid from inserted;
print(#orderId);--allow me to display the inserted order id
SET #maxOrderID = (SELECT Max(orderid) FROM [Products_SumOrders] WHERE MONTH([OrderDate]) = (MONTH(GETDATE())) AND YEAR([OrderDate]) = YEAR(GETDATE()) and orderid < #orderId );
print(#maxOrderID);--last added order
--custom month format (always MM):
declare #mon int;
declare #stringMon nvarchar(10);
set #mon= MONTH(GETDATE());
IF #mon <10
set #stringMon ='0' + CONVERT(VARCHAR(1),#mon) ;
ELSE
set #stringMon = CONVERT(VARCHAR(2),#mon) ;
IF #maxOrderID is null --no orders has been added in this month:
begin
set #maxOrderRef = Substring(CONVERT(VARCHAR(4),YEAR(GETDATE())),3,4)+ '-'+ CONVERT(VARCHAR(2),#stringMon)+'-001';
end
ELSE
--custom order id format (always XXX):
begin
set #relativeID =(SELECT [purchaseOrderRef] FROM [Products_SumOrders] WHERE orderid=#maxOrderID);
set #relativeID = Substring(#relativeID,LEN(#relativeID)-(Charindex('-', REVERSE(#relativeID))-2),LEN(#relativeID));
print(CONVERT(int,#relativeID));
IF CONVERT(int,#relativeID) < 9
set #relativeID ='00' + CONVERT(VARCHAR(2),#relativeID+1) ;
ELSE
begin
if CONVERT(int,#relativeID) < 99
set #relativeID ='0' + CONVERT(VARCHAR(3),#relativeID+1) ;
else
set #relativeID = CONVERT(VARCHAR(3),#relativeID+1) ;
end
set #maxOrderRef = Substring(CONVERT(VARCHAR(4),YEAR(GETDATE())),3,4)+ '-'+ CONVERT(VARCHAR(2),#stringMon)+'-'+ CONVERT(VARCHAR(3),#relativeID);
end
print(#maxOrderRef);
UPDATE Products_SumOrders
SET purchaseOrderRef = #maxOrderRef
FROM inserted INNER JOIN [Products_SumOrders] On inserted.orderid = [Products_SumOrders].orderid
END
GO