portlight
asked on
Concat query does not work when variable are in - how do I fix?
This code works fine. When I try to build it so that the table name (log1644) is dynamic I get errors. (see code below)
This code does not like how I am using the IN variables
DELIMITER //
/* Author: Jessie Brown
Date: 8/17/13
Notes: Template Creation
Comments: Comments created in the header area will NOT be stored in the database write
Comments created AFTer the begin statement will be retained within the database write
*/
-- checks to see if stored procedure exists
-- if exists the procedure is dropped and recreated
DROP PROCEDURE IF EXISTS `reportFreeCoolingTracker`//
-- Creates new procedure
CREATE PROCEDURE reportFreeCoolingTracker (
IN fromDate varchar (50),
IN toDate varchar (50),
IN timeZone varchar (50))
BEGIN
DECLARE startDate varchar (50);
DECLARE endDate varchar (50);
DECLARE mylogID Int;
SET startDate = FROM_UNIXTIME(fromDate/1000);
SET endDate = FROM_UNIXTIME(toDate/1000);
SELECT g.groupId,
g.name AS groupName,
g1.parentId AS parentId1,
g1.name AS group1Name,
g2.parentId AS parentId2,
g2.name AS group2Name,
g3.parentId AS parentId3,
g3.name AS group3Name,
l.logId,l.name AS logName,
l.ordering AS logOrder,
a.activityId AS activityId,
a.ordering AS activityOrder,
a.name AS activityName,
l1.recordId,
l1.started, l1.completed,
l1.userId,l1.note,
u.name,
TO_SECONDS(t2.completed) - TO_SECONDS(l1.completed) AS timeInSeconds,
substr(l.details, instr(l.details , ':' ) +1)AS charge,l.details,
i.itemId,
i.name AS itemName,
i.itemType,
i.details,l1.item31985,l1.item31987,
((l1.item31985 - l1.item31987)*(time_to_sec(timediff(t2.completed, l1.completed)))) / 3600 AS kwDifference,
((l1.item31985 - l1.item31987) * (substr(l.details, instr(l.details , ':' ) +1))) AS cost,
(((l1.item31985 - l1.item31987) * (substr(l.details, instr(l.details , ':' ) +1)))
*(time_to_sec(timediff(t2.completed, l1.completed)) / 3600)) AS costT,
time_to_sec(timediff(t2.completed, l1.completed)) / 3600 AS coolingHours,
time_to_sec(timediff(endDate, startDate)) / 3600 AS totalTimeRange,
(CONVERT_TZ( (FROM_UNIXTIME(fromDate/1000)),'UTC', timeZone) )AS startingDate,
(CONVERT_TZ( (FROM_UNIXTIME(toDate/1000)),'UTC', timeZone) ) AS endingDate,DATABASE() AS databaseName,
CASE
when l1.activityId = t2.activityId THEN 1
ELSE 0
END AS errorCheck
FROM logs l
INNER JOIN groups g ON g.groupId = l.groupId
LEFT JOIN groups g1 ON g.parentId = g1.groupId
LEFT JOIN groups g2 ON g1.parentId = g2.groupId
LEFT JOIN groups g3 ON g2.parentId = g3.groupId
INNER JOIN activities a ON l.logId = a.logId
INNER JOIN log1644 l1 ON a.activityId = l1.activityId
INNER JOIN log1644 t2 ON t2.recordId = l1.recordid + 1
INNER JOIN items i ON l.logId = i.logId AND i.name LIKE '%KW%'
INNER JOIN users u ON l1.userId = u.userId AND i.name LIKE '%KW%'
WHERE i.itemID = "31985" AND l1.activityId = 1257
AND l1.started
BETWEEN startDate
AND endDate
ORDER BY l1.recordId,l1.started;
END //
DELIMITER ;
This code does not like how I am using the IN variables
DELIMITER //
/* Author: Jessie Brown
Date: 8/17/13
Notes: Template Creation
Comments: Comments created in the header area will NOT be stored in the database write
Comments created AFTer the begin statement will be retained within the database write
*/
-- checks to see if stored procedure exists
-- if exists the procedure is dropped and recreated
DROP PROCEDURE IF EXISTS `reportFreeCoolingTrackerTest`//
-- Creates new procedure
CREATE PROCEDURE reportFreeCoolingTrackerTest (
IN fromDate varchar (50),
IN toDate varchar (50),
IN timeZone varchar (50))
BEGIN
DECLARE startDate varchar (50);
DECLARE endDate varchar (50);
DECLARE mylogID Int;
SET startDate = FROM_UNIXTIME(fromDate/1000);
SET endDate = FROM_UNIXTIME(toDate/1000);
SET mylogID = (SELECT logID FROM logs l WHERE l.details LIKE 'FCT%');
SET @tbl = CONCAT('log',mylogID);
set @q1 = CONCAT('SELECT g.groupId,
g.name AS groupName,
g1.parentId AS parentId1,
g1.name AS group1Name,
g2.parentId AS parentId2,
g2.name AS group2Name,
g3.parentId AS parentId3,
g3.name AS group3Name,
l.logId,l.name AS logName,
l.ordering AS logOrder,
a.activityId AS activityId,
a.ordering AS activityOrder,
a.name AS activityName,
l1.recordId,
l1.started, l1.completed,
l1.userId,l1.note,
u.name,
TO_SECONDS(t2.completed) - TO_SECONDS(l1.completed) AS timeInSeconds,
substr(l.details, instr(l.details , '':'' ) +1)AS charge,l.details,
i.itemId,
i.name AS itemName,
i.itemType,
i.details,l1.item31985,l1.item31987,
(l1.item31985 - l1.item31987) AS kwDifference,
((l1.item31985 - l1.item31987) * (substr(l.details, instr(l.details , '':'' ) +1))) AS cost,
(((l1.item31985 - l1.item31987) * (substr(l.details, instr(l.details , '':'' ) +1)))
*(time_to_sec(timediff(t2.completed, l1.completed)) / 3600)) AS costT,
time_to_sec(timediff(t2.completed, l1.completed)) / 3600 AS coolingHours,
time_to_sec(timediff(endDate, startDate)) / 3600 AS totalTimeRange,
(CONVERT_TZ( (FROM_UNIXTIME(fromDate/1000)),''UTC'', timeZone) )AS startingDate,
(CONVERT_TZ( (FROM_UNIXTIME(toDate/1000)),''UTC'', timeZone) ) AS endingDate,DATABASE() AS databaseName
FROM logs l
INNER JOIN groups g ON g.groupId = l.groupId
LEFT JOIN groups g1 ON g.parentId = g1.groupId
LEFT JOIN groups g2 ON g1.parentId = g2.groupId
LEFT JOIN groups g3 ON g2.parentId = g3.groupId
INNER JOIN activities a ON l.logId = a.logId
INNER JOIN ',@tbl);
set @q2 = CONCAT( @q1,' l1 ON a.activityId = l1.activityId
INNER JOIN ');
set @q3 = CONCAT(@q2 , @tbl);
SET @q4 = CONCAT(@q3,' t2 ON t2.recordId = l1.recordid + 1
INNER JOIN items i ON l.logId = i.logId AND i.name LIKE ''%KW%''
INNER JOIN users u ON l1.userId = u.userId AND i.name LIKE ''%KW%''
WHERE i.itemID = "31985" AND l1.activityId = 1257
AND l1.started
BETWEEN startDate
AND endDate
ORDER BY l1.started');
PREPARE stmt FROM @q4;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
ASKER
Will not compile
Gives me an error at PREPARE stmt FROM myQuery;
error: unexpected symbol myQuery
Gives me an error at PREPARE stmt FROM myQuery;
error: unexpected symbol myQuery
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
To actually solve the problem, you have two choices:
- step outside the quotes around the variable names, just like you do for the table names. Since these are dates, you'll need to QUOTE() them:
- use '?' placeholders, and then execute the prepared statement with user variable parameters:
- step outside the quotes around the variable names, just like you do for the table names. Since these are dates, you'll need to QUOTE() them:
set @q1 = CONCAT('SELECT ... (FROM_UNIXTIME(', QUOTE(fromDate), '/1000...
- use '?' placeholders, and then execute the prepared statement with user variable parameters:
SET @fromDate = fromDate;
set @q1 = CONCAT('SELECT ... (FROM_UNIXTIME(?/1000...
PREPARE stmt FROM @q1;
EXECUTE stmt USING @fromDate;
ASKER
I was able to get this to pull, however every place that uses the timeZone, toDate, fromDate, endDate and startDate return nulls. So I know I am not actually passing the input variables into the query correctly
SET @myQuery = CONCAT('SELECT g.groupId,
g.name AS groupName,
g1.parentId AS parentId1,
g1.name AS group1Name,
g2.parentId AS parentId2,
g2.name AS group2Name,
g3.parentId AS parentId3,
g3.name AS group3Name,
l.logId,l.name AS logName,
l.ordering AS logOrder,
a.activityId AS activityId,
a.ordering AS activityOrder,
a.name AS activityName,
l1.recordId,
l1.started, l1.completed,
l1.userId,l1.note,
u.name,
TO_SECONDS(t2.completed) - TO_SECONDS(l1.completed) AS timeInSeconds,
substr(l.details, instr(l.details , '':'' ) +1)AS charge,l.details,
i.itemId,
i.name AS itemName,
i.itemType,
i.details,l1.item31985,l1.item31987,
(l1.item31985 - l1.item31987) AS kwDifference,
((l1.item31985 - l1.item31987) * (substr(l.details, instr(l.details , '':'' ) +1))) AS cost,
(((l1.item31985 - l1.item31987) * (substr(l.details, instr(l.details , '':'' ) +1)))
*(time_to_sec(timediff(t2.completed, l1.completed)) / 3600)) AS costT,
time_to_sec(timediff(t2.completed, l1.completed)) / 3600 AS coolingHours,
time_to_sec(timediff(@endDate, @startDate)) / 3600 AS totalTimeRange,
(CONVERT_TZ( (FROM_UNIXTIME(@fromDate/1000)),''UTC'', @timeZone) )AS startingDate,
(CONVERT_TZ( (FROM_UNIXTIME(@toDate/1000)),''UTC'', @timeZone) ) AS endingDate,DATABASE() AS databaseName
FROM logs l
INNER JOIN groups g ON g.groupId = l.groupId
LEFT JOIN groups g1 ON g.parentId = g1.groupId
LEFT JOIN groups g2 ON g1.parentId = g2.groupId
LEFT JOIN groups g3 ON g2.parentId = g3.groupId
INNER JOIN activities a ON l.logId = a.logId
INNER JOIN ', @tbl,' l1 ON a.activityId = l1.activityId
INNER JOIN ', @tbl,' t2 ON t2.recordId = l1.recordid + 1
INNER JOIN items i ON l.logId = i.logId AND i.name LIKE ''%KW%''
INNER JOIN users u ON l1.userId = u.userId AND i.name LIKE ''%KW%''
WHERE i.itemID = "31985" AND l1.activityId = 1257
ORDER BY l1.started');
PREPARE stmt FROM @myQuery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
ASKER
While the query compiles and passes most of the data - any of the date calculations that are using variable are not passing
Your method will work if you assign those user variables to hold the same values as your parameters first:
SET @timeZone = timeZone;
SET @fromDate = fromDate;
etc.
SET @timeZone = timeZone;
SET @fromDate = fromDate;
etc.
DELIMITER //
/* Author: Jessie Brown
Date: 8/17/13
Notes: Template Creation
Comments: Comments created in the header area will NOT be stored in the database write
Comments created AFTer the begin statement will be retained within the database write
*/
-- checks to see if stored procedure exists
-- if exists the procedure is dropped and recreated
DROP PROCEDURE IF EXISTS `reportFreeCoolingTrackerT
-- Creates new procedure
CREATE PROCEDURE reportFreeCoolingTrackerTe
IN fromDate varchar (50),
IN toDate varchar (50),
IN timeZone varchar (50))
BEGIN
DECLARE startDate varchar (50);
DECLARE endDate varchar (50);
DECLARE mylogID Int;
DECLARE myQuery varchar(2000);
SET startDate = FROM_UNIXTIME(fromDate/100
SET endDate = FROM_UNIXTIME(toDate/1000)
SET mylogID = (SELECT logID FROM logs l WHERE l.details LIKE 'FCT%');
SET @tbl = CONCAT('log',mylogID);
SELECT myQuery = CONCAT('SELECT g.groupId,
g.name AS groupName,
g1.parentId AS parentId1,
g1.name AS group1Name,
g2.parentId AS parentId2,
g2.name AS group2Name,
g3.parentId AS parentId3,
g3.name AS group3Name,
l.logId,l.name AS logName,
l.ordering AS logOrder,
a.activityId AS activityId,
a.ordering AS activityOrder,
a.name AS activityName,
l1.recordId,
l1.started, l1.completed,
l1.userId,l1.note,
u.name,
TO_SECONDS(t2.completed) - TO_SECONDS(l1.completed) AS timeInSeconds,
substr(l.details, instr(l.details , '':'' ) +1)AS charge,l.details,
i.itemId,
i.name AS itemName,
i.itemType,
i.details,l1.item31985,l1.
(l1.item31985 - l1.item31987) AS kwDifference,
((l1.item31985 - l1.item31987) * (substr(l.details, instr(l.details , '':'' ) +1))) AS cost,
(((l1.item31985 - l1.item31987) * (substr(l.details, instr(l.details , '':'' ) +1)))
*(time_to_sec(timediff(t2.
time_to_sec(timediff(t2.co
time_to_sec(timediff(endDa
(CONVERT_TZ( (FROM_UNIXTIME(fromDate/10
(CONVERT_TZ( (FROM_UNIXTIME(toDate/1000
FROM logs l
INNER JOIN groups g ON g.groupId = l.groupId
LEFT JOIN groups g1 ON g.parentId = g1.groupId
LEFT JOIN groups g2 ON g1.parentId = g2.groupId
LEFT JOIN groups g3 ON g2.parentId = g3.groupId
INNER JOIN activities a ON l.logId = a.logId
INNER JOIN ', @tbl,' l1 ON a.activityId = l1.activityId
INNER JOIN ', @tbl,' t2 ON t2.recordId = l1.recordid + 1
INNER JOIN items i ON l.logId = i.logId AND i.name LIKE ''%KW%''
INNER JOIN users u ON l1.userId = u.userId AND i.name LIKE ''%KW%''
WHERE i.itemID = "31985" AND l1.activityId = 1257
AND l1.started
BETWEEN startDate
AND endDate
ORDER BY l1.started');
PREPARE stmt FROM myQuery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;