I am trying to use while loop in my stored procedure, but it doesn't want to accept the syntax.
I am using HeidiSQL as a Studio, database is MySQL MariaDB.
BEGIN
CREATE TEMPORARY TABLE taskTemp
SELECT jc.Id as JID
FROM jobs as j
left join jobcards as jc on j.JobcardId = jc.Id
left join tasks as t on j.Id = t.JobId
left join assignments as a ON t.Id = a.TaskId
WHERE a.PerformerId = currentUserId
group by jc.Id;
SELECT GROUP_CONCAT(JID SEPARATOR ',') AS result
INTO #test
FROM taskTemp;
CREATE TEMPORARY TABLE UserTasks
Select j.Id ,j.JobcardId as JcID, t.Id as TaskID ,js.Name as TaskStatus
from jobs as j
left join tasks as t on j.Id = t.JobId
Join assignments as a on t.Id = a.TaskId and a.PerformerId = currentUserId
left Join jobstatuses as js on t.StatusId = js.Id
WHERE FIND_IN_SET(j.JobcardId, #test);
alter table UserTasks add UserStatus longtext;
SET #n=0;
SET #i=0;
SELECT COUNT(*) FROM UserTasks INTO #n;
WHILE (#n>0) DO
SET #n=#n-1;
END WHILE;
drop temporary table taskTemp;
drop temporary table UserTasks;
END
Above you can see my whole stored procedure, so the problem is coming at this row:
WHILE (#n>0) DO
SET #n=#n-1;
END WHILE;*
*
I have tried without brackets also #n>0, but also without success
I think this is an issue with SQL mode configuration in your mariadb environment. You can try one of the following options :
1. Use oracle loop syntax :
SET #n=5;
WHILE #n>0 LOOP
SET #n=#n-1;
SELECT #n;
END LOOP;
2. Change sql mode to tradionnal :
SET sql_mode = 'TRADITIONAL';
SET GLOBAL sql_mode = 'TRADITIONAL';
Related
I am working on converting a T-SQL stored procedure into MySQL. I am not familiar with T-SQL and am working on becoming more familiar with temp tables and stored procedures. Thanks for your help in advance.
The T-SQL original looks like this (EDIT: note this is only a portion of the original procedure used to produce a report):
DROP TABLE IF EXISTS #accounts;
SELECT d.data_id
,p.pp_name AS name
,CONVERT(tinyint,1) AS flag
,d.pd_date
,CONVERT(char(6),pd_date,112) AS date_period
,CONVERT(varchar(3),0) AS n_phones
INTO #accounts
from table_detail d
JOIN table_pool p ON d.pp_id = p.pp_id
JOIN table_type t ON p.pp_type_id = t.pp_type_id
JOIN Inventory i ON d.data_id = i.data_id
JOIN Product pr ON i.product_id = pr.product_id
WHERE pp_name IN (SELECT name FROM Sandbox..desired_sandbox)
AND DATEDIFF(MONTH,pd_date,GETDATE()) < 3
UPDATE a
SET a.flag = 0
FROM #accounts a
JOIN table_detail d ON a.data_id = d.data_id
JOIN table_pool p ON d.pp_id = p.pp_id
WHERE d.pd_date < a.pd_date
AND pp_name != 'error';
My current update is below. Do I need to wrap this in a CREATE TEMPORARY TABLE IF NOT EXISTS accounts AS (<insert query here>) instead of the INTO #accounts?
SELECT d.data_id
,p.pp_name AS name
,CONVERT(tinyint,1) AS flag
,d.pd_date
,DATE_FORMAT(pd_date,'%Y%m%d') AS date_period
,CONVERT(varchar(3),0) AS n_phones
FROM table_detail d
JOIN table_pool p ON d.pp_id = p.pp_id
JOIN table_type t ON p.pp_type_id = t.pp_type_id
JOIN Inventory i ON d.data_id = i.data_id
JOIN Product pr ON i.product_id = pr.product_id
WHERE pp_name IN (SELECT name FROM Sandbox..desired_sandbox)
AND TIMESTAMPDIFF(MONTH,pd_date,NOW()) < 3
Then do something like this assuming the syntax is right:
UPDATE accounts a -- Is this the correct way to add an alias and update the temp table?
JOIN table_detail d ON a.data_id = d.data_id
JOIN table_pool p ON d.pp_id = p.pp_id
SET a.flag = 0
WHERE d.pd_date < a.pd_date
AND pp_name != 'error';
Finally, I assume I could follow this post to wrap the final query into a stored procedure, correct? To summarize the code in the post:
drop procedure if exists procedure_name;
DELIMITER $$
create procedure procedure_name ()
BEGIN
DROP TEMPORARY TABLE IF EXISTS accounts;
CREATE TEMPORARY TABLE accounts AS (
SELECT...
FROM...
WHERE...
;
)
UPDATE accounts
JOIN ...
JOIN ...
SET...
WHERE...;
DROP TEMPORARY TABLE accounts; -- otherwise it survives the stored proc call
END
$$ -- signify end of block
DELIMITER ; -- reset to default delimiter
I wanted to post the solution that finally worked for me for others that might be having the same issue. The code below resolves this.
DROP PROCEDURE IF EXISTS procedure_name;
DELIMITER $$
CREATE PROCEDURE procedure_name ()
BEGIN
DROP TEMPORARY TABLE IF EXISTS accounts;
CREATE TEMPORARY TABLE accounts AS (
SELECT d.data_id
,p.pp_name AS name
,1 AS flag
,d.pd_date
,DATE_FORMAT(pd_date,'%Y%m%d') AS date_period
,CONVERT(varchar(3),0) AS n_phones
FROM table_detail d
JOIN table_pool p ON d.pp_id = p.pp_id
JOIN table_type t ON p.pp_type_id = t.pp_type_id
JOIN Inventory i ON d.data_id = i.data_id
JOIN Product pr ON i.product_id = pr.product_id
WHERE pp_name IN (SELECT name FROM Sandbox..desired_sandbox)
AND TIMESTAMPDIFF(MONTH,pd_date,NOW()) < 3
);
-- Update the temp table based on specified criteria
UPDATE accounts
JOIN ...
JOIN ...
SET...
WHERE...;
-- Create final Query for report
SELECT ...
FROM accounts
WHERE ...
GROUP BY ... -- whatever you need for final query
DROP TEMPORARY TABLE accounts; -- otherwise it survives the stored proc call
END
$$ -- signify end of block
DELIMITER ; -- reset to default delimiter
However, it is important to note the limits of MySQL temporary tables. Although I did not indicate it in my original post, later, I was attempting to join the temporary table onto itself. I needed to follow the suggestion outlined here. Essentially, if you need to refer to a temp table with itself you need to make a copy of the temp table: CREATE TEMPORARY TABLE accounts2 AS (SELECT * FROM accounts). Then you can join a temp table to itself.
I would like to know if there are ways I could optimize n improve performance of this stored procedure. I'm fairly new at it & would appreciate your help.
This procedure I Inherited from the previous programmer.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spDailyWorkConfB]
#datew DATETIME
AS
BEGIN
SET NOCOUNT ON;
;WITH tmpTable AS
(
SELECT IdRealizare,Adresa, CONVERT(char(2), Data, 108) as Ora
FROM Butoane
WHERE (IdRealizare <> 0) AND (DAY(butoane.Data) = DAY(#datew)) AND (MONTH(butoane.Data) = MONTH(#datew)) AND (YEAR(butoane.Data) = YEAR(#datew))
)
SELECT *, COUNT(*) AS Qty INTO #tblOne
FROM tmpTable
GROUP BY IdRealizare,Adresa,Ora
HAVING COUNT(*) >=1
ORDER BY Ora
SELECT Masini.Linie , Masini.CodMasina, Operatii.CodOperatie, Angajati.Angajat, Comenzi.NrComanda,Articole.Articol,
OperatiiArticol.BucatiButon,Operatii.Operatie,OperatiiArticol.BucatiOra, Masini.Grup, #tblone.Ora, #tblOne.Qty, Realizari.Id, Operatii.PozRaport, Angajati.IdSector, Realizari.LastWrite,
Articole.Stagione
INTO #tblFOR
FROM Realizari
INNER JOIN Masini ON Realizari.IdMasina = Masini.Id
INNER JOIN Angajati ON Realizari.IdAngajat = Angajati.Id
INNER JOIN Comenzi ON Realizari.IdComanda = Comenzi.Id
INNER JOIN Operatii ON Realizari.IdOperatie = Operatii.Id
INNER JOIN Articole ON Comenzi.IdArticol = Articole.Id
INNER JOIN OperatiiArticol ON Comenzi.IdArticol = OperatiiArticol.IdArticol AND Operatii.id = OperatiiArticol.IdOperatie
INNER JOIN #tblOne ON #tblOne.IdRealizare=Realizari.Id
SELECT * FROM #tblFOR WHERE Qty>0 AND IdSector='1' AND Linie in ('LINEA1','LINEA2','LINEA3','LINEA4','LINEA5','LINEA6','LINEA7','LINEA8','LINEA9','LINEA10','LINEA11','LINEA12') ORDER BY Realizari.Id
END
If some one have some idea I would like to hear that.
Thank you, best regards.
One tip is that you should use WITH (NOLOCK) in your join query. Since this procedures basically build to show up the data So It is better that you may get uncommitted data rather than creating a deadlock when other queries performing update on those tables.
I am trying to performing update operation on value which meet certain criteria. My tables CAPD, CAMP, CAD. But I get error of
Error Code: 1093. You can't specify target table 'CAPD' for update in
FROM clause
UPDATE CAPD SET CAPD.Is_Active = 1
WHERE CAPD.Per_Id IN (
SELECT CAMP.Id
FROM CAMP
INNER JOIN CAPD ON (
CAPD.Per_Id = CAMP.Id
AND CAPD.Is_Active = 0
)
INNER JOIN CAD ON (
CAD.Id = CAPD.Deploy_Id
AND BINARY CAD.Access_Id = "486579446F6E277-4436F6E7665727449742E2E4C-4F4C203A5020584F586F"
)
WHERE CAMP.Serial = "ABC1230071"
)
You cannot use the target table which you are updating inside the
subquery. You need to use the JOIN in case you want to use it -- First
answer by #Rahul Tripathi
You have to try this query then you need to set SET SQL_SAFE_UPDATES
SET SQL_SAFE_UPDATES=0;
UPDATE CAPD
INNER JOIN CAD ON ( CAD.Id = CAPD.Deploy_Id)
SET CAPD.Is_Active = 1
WHERE CAPD.Per_Id IN (
SELECT CAMP.Id
FROM CAMP
WHERE CAMP.Serial = "ABC1230071"
)
AND BINARY CAD.Access_Id = "486579446F6E277-4436F6E7665727449742E2E4C-4F4C203A5020584F586F";
SET SQL_SAFE_UPDATES=1;
You cannot use the target table which you are updating inside the subquery. You need to use the JOIN in case you want to use it. Try like this:
UPDATE CAPD
INNER JOIN CAD ON ( CAD.Id = CAPD.Deploy_Id)
SET CAPD.Is_Active = 1
WHERE CAPD.Per_Id IN (SELECT CAMP.Id
FROM CAMP
WHERE CAMP.Serial = "ABC1230071" )
and CAD.Access_Id = "486579446F6E277-4436F6E7665727449742E2E4C-4F4C203A5020584F586F"
and CAPD.Is_Active = 0
I want to run some updates on my MySQL database. Here is the query that I want to use:
UPDATE `wphh_wp_eStore_tbl`
SET `wphh_wp_eStore_tbl`.description = '<div class="dwrp">
<h2>F. Locker $109.99</h2>
<h2>Nike Outlet $109.99</h2>
<h2>Ch. Sports $107.99</h2>
<h2>Hoopers Hookup $89.99</h2>
<h2 class="special">These prices as of 11/20/13</h2>'
WHERE `wphh_wp_eStore_tbl`.id in (
SELECT `wphh_wp_eStore_tbl`.id FROM `wphh_wp_eStore_tbl`
INNER JOIN `wphh_wp_eStore_cat_prod_rel_tbl`
on `wphh_wp_eStore_cat_prod_rel_tbl`.prod_id = `wphh_wp_eStore_tbl`.id
WHERE `wphh_wp_eStore_cat_prod_rel_tbl`.cat_id = 5
)
This generates the following error:
#1093 - You can't specify target table 'wphh_wp_eStore_tbl' for update in FROM clause
Why? I know in MSSQL I can do this:
Update tableone
set columnname = 'xxx'
where id in (
select id
from tableone
where category = 10)
and it works.
What am I missing?
The simple solution is to enclose the in list in an additional level of nesting. MySQL will then materialize the data:
UPDATE `wphh_wp_eStore_tbl`
SET `wphh_wp_eStore_tbl`.description = '<div class="dwrp">
<h2>F. Locker $109.99</h2>
<h2>Nike Outlet $109.99</h2>
<h2>Ch. Sports $107.99</h2>
<h2>Hoopers Hookup $89.99</h2>
<h2 class="special">These prices as of 11/20/13</h2>'
WHERE `wphh_wp_eStore_tbl`.id in (
select * from (SELECT `wphh_wp_eStore_tbl`.id FROM `wphh_wp_eStore_tbl`
INNER JOIN `wphh_wp_eStore_cat_prod_rel_tbl` on `wphh_wp_eStore_cat_prod_rel_tbl`.prod_id = `wphh_wp_eStore_tbl`.id
WHERE
`wphh_wp_eStore_cat_prod_rel_tbl`.cat_id = 5) t
)
Another way is to use join to with update.
I'm not a MySQL guy but could you do this instead? I also like using table alias with these ugly names.
UPDATE `wphh_wp_eStore_tbl` e
inner join `wphh_wp_eStore_cat_prod_rel_tbl` ecpr
on ecpr.prod_id = e.id
and ecpr.cat_id = 5
set e.description = 'Some Text To Update With'
In SQL Server the "from" and the join come after the SET but.. not the case in mySQL apparently.
Here's my code I'm trying to get working to no avail:
CREATE DEFINER=`auser`#`localhost` PROCEDURE `listings_set_image`(
IN inPropertyId INT, IN inImage VARCHAR(150), IN inCaption(255))
BEGIN
INNER JOIN property_images pi
ON pi.image_id = i.image_id
UPDATE images i SET i.image_name = inImage, i.image_caption = inCaption
WHERE pi.property_id = inPropertyId;
END//
What am I not doing properly?
Your UPDATE syntax is incorrect; the join should form part of table_references:
UPDATE images i JOIN property_images pi USING (image_id)
SET i.image_name = inImage, i.image_caption = inCaption
WHERE pi.property_id = inPropertyId;