sql trigger unable to set variable from select - mysql

I know its asked question ,however I have tried few amendments but to no solution .
My trigger:
BEGIN
DECLARE bookid INT;
DECLARE roomtype varchar(20);
DECLARE amount INT;
DECLARE m_count INT;
DECLARE curr_m varchar(20);
SET #bookid := NEW.id;
SET roomtype := (SELECT title FROM pm_booking_room WHERE id_booking=#bookid);
SET amount := (SELECT amount from pm_booking_payment WHERE id_booking=#bookid);
SET #curr_m:= (MONTHNAME(NOW()));
SET #m_count:= (SELECT count(*) FROM pm_report WHERE month=#curr_m);
INSERT INTO `pm_report`(`month`, `room_type`, `amount`) VALUES(#curr_m,#roomtype,#amount);
END
whwn I check table, it inserts, but only #curr which is month name. Rest it inserts NULL
I tried
SET #roomtype SELECT title FROM pm_booking_room WHERE id_booking=#bookid but still same,NULL .
Also tried SET #roomtype := (SELECT title FROM pm_booking_room WHERE id_booking=#bookid); but still NULL.
I am using PhpMyadmin to create :
Please help.

Please be aware that roomtype and #roomtype are two different variables.
The variables you declare with the local variable DECLARE statement have a scope within the body of one stored routine. They are never spelled with a # sigil.
The user-defined variables with the # sigil have a scope of a MySQL session. You don't need to declare these kinds of variables. Just setting the variable to a value implicitly creates the variable.
You cannot SET roomtype = ... and expect that string to be read from the #roomtype variable. Nor vice-versa.
You appear to declare local variables, so you should use them consistently. But in some cases, your variable names are the same as column names, which will result in ambiguity if you use the variables in SQL statements that also reference tables with those columns. So you should adopt a naming convention to keep them distinct.
BEGIN
DECLARE v_bookid INT;
DECLARE v_roomtype varchar(20);
DECLARE v_amount INT;
DECLARE v_count INT;
DECLARE v_month varchar(20);
SET v_bookid := NEW.id;
SET v_roomtype := (SELECT title FROM pm_booking_room WHERE id_booking=v_bookid);
SET v_amount := (SELECT amount from pm_booking_payment WHERE id_booking=v_bookid);
SET v_month:= (MONTHNAME(NOW()));
SET v_count:= (SELECT count(*) FROM pm_report WHERE month=v_month);
INSERT INTO `pm_report`(`month`, `room_type`, `amount`) VALUES(v_month,v_roomtype,v_amount);
END
(This code is not tested, so apologies if there are any mistakes. It is meant only to demonstrate using non-sigil variables consistently.)

Related

Not able to assign month,day and year into local variables in mysql stored procedure even though data is there

I have to extract day, month and year of a date into variable and then do some updation on table
Problem I am having is that though i am able to get the result set by the local fields alway appear null
Mysql query is
DECLARE ExistingRecordYear INT;
DECLARE ExistingRecordMonth INT;
DECLARE ExistingRecordDay INT;
DECLARE CountRecords SMALLINT;
SELECT COUNT(*) , ExistingRecordYear = YEAR(updatedon),
ExistingRecordMonth = MONTH(updatedon), ExistingRecordDay = DAY(updatedon)
FROM `transactions`
WHERE `issuer_id` = _issuer_id
AND `msisdn` = _msisdn ;
Though updatedon is not a nullable field and my count result is 1 but i am still seeing null in all three fields of month,year,and day
Please help me in it
In a select statement, you use := to assign variables, not =. In addition, you probably want your variables to have a prefix to distinguish them from columns. Something like:
DECLARE v_ExistingRecordYear INT;
DECLARE v_ExistingRecordMonth INT;
DECLARE v_ExistingRecordDay INT;
DECLARE v_CountRecords SMALLINT;
SELECT v_CountRecords := COUNT(*) , v_ExistingRecordYear := YEAR(updatedon),
v_ExistingRecordMonth := MONTH(updatedon), v_ExistingRecordDay := DAY(updatedon)
FROM `transactions`
WHERE `issuer_id` = _issuer_id AND `msisdn` = _msisdn ;

OUTPUT TO MULTIPLE FILES FROM A SINGLE QUERY

I am a little stuck... I am trying to take the output from a query and break it into numerous files based on a single criteria. I am getting an error of converting a varchar type to int and I cannot figure out why. Working in SQL Server 2008...
DECLARE #LOOP AS INT;
DECLARE #SQL AS VARCHAR(MAX);
DECLARE #BCP AS VARCHAR(MAX);
DECLARE #COUNTER AS INT;
DECLARE #FILENAME AS VARCHAR(MAX);
SET #COUNTER='1'
SELECT #LOOP = COUNT(DISTINCT LIST_ID) FROM DATA_TABLE
WHERE STATUS='2' AND LIST_ID IS NOT NULL ;
SET #SQL=(SELECT CUSTOMER_NO FROM CUSTOMER A, DATA_TABLE B
WHERE A.CUSTOMER_ID=B.CUSTOMER_ID AND A.STATUS='2' AND LIST_ID='+#LOOP+');
SET #FILENAME='QUERYOUT C:\Projects\FILE_"'+#LOOP+'.TXT'
WHILE #COUNTER<=#LOOP
BEGIN
SELECT
#BCP='BCP "'+#SQL+'+'+#FILENAME+''
SET #COUNTER=#COUNTER+1
END
GO
The error I am getting is:
Msg 245, Level 16, State 1, Line 10
Conversion failed when converting the varchar value '+#LOOP+' to data type int.
I am trying to use the LOOP value to let me know the contents of each file. For example, LOOP='1' would mean the file contains the customer records associate with LIST_ID='1'
Thoughts on the error?
I'm not sure I understand exactly what you need but if you want to issue the BCP command for every LIST_ID you need to loop though them and execute for each one.
This may not be what you need but rather than wait until I am home from work I will post it now.
DECLARE #FILENAME AS VARCHAR(MAX);
DECLARE #LISTID INT
DECLARE #LOOP AS INT;
DECLARE #BCP AS VARCHAR(MAX);
DECLARE #SQL AS VARCHAR(MAX);
DECLARE cur CURSOR FOR SELECT DISTINCT LIST_ID FROM DATA_TABLE WHERE STATUS='2' AND LIST_ID IS NOT NULL
OPEN cur
FETCH NEXT FROM cur INTO #LISTID
WHILE ##FETCH_STATUS = 0 BEGIN
SET #FILENAME='QUERYOUT C:\Projects\FILE_'+Cast(#LISTID AS Varchar)+'.TXT -c -t -T'
SET #SQL='(SELECT CUSTOMER_NO FROM CUSTOMER A, DATA_TABLE B WHERE A.CUSTOMER_ID=B.CUSTOMER_ID AND A.STATUS=''2'' AND LIST_ID='+#LISTID+')';
SELECT #BCP='BCP '+#SQL+' '+#FILENAME+''
EXEC xp_cmdshell #BCP
FETCH NEXT FROM cur INTO #LISTID
END
CLOSE cur
DEALLOCATE cur
1.change varchar(max) to varchar(8000)
2.Add DBNAME.SCHEMA for all the tables, because by default it will point to the Master db.
Added double quotes(") below
3. #FILENAME='QUERYOUT "C:\Projects\FILE_'+Cast(#LISTID AS Varchar)+'.TXT" -c -t -T'
4. '("SELECT CUSTOMER_NO FROM CUSTOMER A, DATA_TABLE B WHERE A.CUSTOMER_ID=B.CUSTOMER_ID AND A.STATUS=''2'' AND LIST_ID='+#LISTID+'")';

Mysql FETCH CURSOR result ununderstood

I've been Googleing around for a while and I am sure that the problem is that I don't understand clearly how CURSORs in MySQL work.
A short explanation of the problem: I'm writing such function (simplified):
CREATE DEFINER=`me`#`localhost` FUNCTION `product_move`(prID INT, tr_type VARCHAR(2), clID INT, am INT, dnID INT, usrID INT, price FLOAT(10,2), ti DATETIME, barc TINYTEXT, cmt TINYTEXT, lnID INT)
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE cur_id INT;
DECLARE net_pr FLOAT(10,2);
DECLARE cur_r INT;
DECLARE remaind INT DEFAULT 0;
DECLARE avg_price FLOAT(10,2) DEFAULT 0;
DECLARE curs CURSOR FOR SELECT `products_transactionsID`,
`price`,
`remains`
FROM `products_transactions`
WHERE `productID`=prID AND `remains`>0 AND `type`='V'
ORDER BY `products_transactionsID` ASC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN curs;
SET remaind=am;
read_loop:LOOP
FETCH curs INTO cur_id,net_pr,cur_r;
IF done THEN
LEAVE read_loop;
END IF;
IF (cur_r>=remaind) THEN
SET avg_price = avg_price + (net_pr * remaind);
UPDATE `products_transactions` SET `remains`=`remains`-remaind WHERE products_transactionsID=cur_id;
LEAVE read_loop;
ELSE
SET avg_price = avg_price + (net_pr * cur_r);
SET remaind=remaind-cur_r;
UPDATE `products_transactions` SET `remains`=0 WHERE products_transactionsID=cur_id;
END IF;
END LOOP;
CLOSE curs;
SET avg_price=avg_price/am;
INSERT INTO products_transactions
(`products_transactionsID`,`clientID`,`date_created`,`delivery_notesID`,`type`,`productID`,`amountIN`,`amountOUT`,`barcodes`,`in_stock`,`out_stock`,`out_repair`,`out_loss`,`booked`,`ordered`,`userID`,`price`,`comments`,`fifo_buy_price`)
SELECT NULL, clID, ti, dnID , tr_type, prID, 0, am, barc, products_transactions.in_stock-am, products_transactions.out_stock,
products_transactions.out_repair, products_transactions.out_loss, products_transactions.booked, products_transactions.ordered,usrID,price,cmt,avg_price
FROM
products_transactions WHERE productID=prID ORDER BY products_transactionsID DESC LIMIT 1;
So, we insert a new row in this table, based upon some calculations from the previously selected rows and updating these rows meanwhile.
The problem is with the avg_price variable, which should be calculated based on the net_pr variable which is FETCH'ed from the cursor. But somehow, instead of being FETCH'ed from the SELECT, the net_pr variable takes the value of the price input parameter of my function! How is that possible?
My guesses have been so far:
a variable name conflict? Searched through the code but I can't find any.
updating the table within the LOOP could make the CURSOR loose its position? It would make sense, but that wouldn't result in this, either...
I'd apreciate any ideas.
Two things that I can see:
1) Don't update the table that you're using in the cursor. MySQL says the cursor is read only but I wouldn't trust this. Set your value, exit the cursor, and then update the table.
2) Using the same name for a variable in the proc definition and a column in a select gives a conflict: http://dev.mysql.com/doc/refman/5.0/en/local-variable-scope.html
"A local variable should not have the same name as a table column. If an SQL statement, such as a SELECT ... INTO statement, contains a reference to a column and a declared local variable with the same name, MySQL currently interprets the reference as the name of a variable. "

SQL Set IDENTITY Field Using Variable

All, I want to start the numbering of an IDENTITY field based on the current maximum obtained from another table. So I have tried something like the following
DECLARE #CurrentES INT;
SET #CurrentES = (SELECT MaxES
FROM [NDB]..[TmpMaxES]) + 1;
ALTER TABLE BA
ADD ES INT IDENTITY(#CurrentES, 1);
But this will not accept a variable as the seed value in IDENTITY. How can what I require be achieved?
Thanks for your time.
Do do this and other non-variable allowed tasks, you can use the EXEC function, as follows:
DECLARE #CurrentES INT;
SET #CurrentES = (SELECT MaxES
FROM [NDB]..[TmpMaxES]) + 1;
DECLARE #Statement VARCHAR(200)
SET #Statement = 'ALTER TABLE BA
ADD ES INT IDENTITY(' + CAST(#CurrentES AS VARCHAR) + ', 1);'
EXEC (#Statement)
You could use the dbcc checkident feature of SQL Server...
DECLARE #MAXID INT
SELECT #MAXID = MAX(ID_FIELD) FROM OLDTABLE
dbcc checkident(NEWTABLE, reseed, #MAXID)
One thing to note with this is that the value in the 3rd parameter (in this case the #MAXID variable) denotes the current identity value - in other words the last identity value that was generated on the table.
So, for example, if you want the next value that is automatically created to be 100, then set the 3rd parameter to 99.
--first variable
declare #code varchar(50);
set #code=1345688867567576;
--second variable
declare #namedb varchar(50);
set #namedb='test';
--let's you add to the identity(ID) field
SET IDENTITY_INSERT dbo.nameAndroid ON
--declaring variable to hold the next id number
declare #id int;
set #id=##IDENTITY +1;
--clause to check if the table has the matching barcode
if not exists (select * from dbo.nameAndroid where barcode = #code)
INSERT INTO dbo.nameAndroid (id, name, barcode, [floor], Column1,Column2,Row1,Row2,Shelf,Stock,OnOrder)
VALUES ( #id,#namedb, #code, 'Value3', 'Value4','Value5','Value6','Value7','Value8',123,600);
SET IDENTITY_INSERT dbo.nameAndroid OFF;
OR (if the id column is of type int)
declare #code varchar(50);
set #code='123211';
declare #namedb varchar(50);
set #namedb='test';
declare #floordb varchar(50);
set #floordb='test';
declare #Column1db varchar(50);
set #Column1db='test';
declare #Column2db varchar(50);
set #Column2db='test';
declare #Row1db varchar(50);
set #Row1db='test';
declare #Row2db varchar(50);
set #Row2db='test';
declare #Shelfdb varchar(50);
set #Shelfdb='test';
declare #OnOrderdb decimal(18,2);
set #OnOrderdb=10010;
declare #Stockdb decimal(18,2);
set #Stockdb=1010101;
declare #id int;
set #id=((select max(id) from dbo.nameAndroid )+1);
if not exists (select * from dbo.nameAndroid where barcode = #code)
begin
SET IDENTITY_INSERT dbo.nameAndroid ON;
INSERT INTO dbo.nameAndroid (id, name, barcode, [floor], Column1,Column2,Row1,Row2,Shelf,Stock,OnOrder)
VALUES (#id, #namedb, #code, #floordb, #Column1db,#Column2db,#Row1db,#Row2db,#Shelfdb,#OnOrderdb,#Stockdb);
SET IDENTITY_INSERT dbo.nameAndroid OFF;
end
Try something like this..
SET IDENTITY_INSERT [MyTable] ON
INSERT INTO [MyTable] ... (MAX) Value from another table and other applicable record.
...
SET IDENTITY_INSERT [MyTable] OFF

mysql declaring and setting variables. syntax errors

I thought this would be a simple task but i cannot figure out why this gives me an error in my syntax. Any help is appreciated.
DECLARE #usernameid VARCHAR(20);
declare #UserIDParam VARCHAR(20);
SET #usernameid = 'myid';
SET #UserIDParam =
(SELECT userid
FROM tblusers
WHERE unid = usernameid);
SELECT *
FROM tblusers
WHERE tblusers.userID = #useridparam
One doesn't DECLARE user variables: one just uses them. (You DECLARE local variables e.g. in a procedure).