Debugging a MySQL procedure in phpMyAdmin - mysql

I have a really basic question that I've been unable to find the answer to so far. I've read several answers but they don't seem to be working for me.
I'm not looking for someone to debug this (unless you are feeling super helpful!) I just would like some help to debug it myself.
I have the following procedure that I'm in the process of writing. I've obviously made a mistake but can someone show me the best way to debug this. When I call this procedure in phpMyAdmin I can't see what the value of #sql is.
I tried entering SELECT #sql; but that didn't seem to work as nothing was displayed when I called the procedure.
How can I find out what the value of #sql is so that I can properly debug this.
Thanks in advance.
BEGIN
set #sql = (select concat('SELECT a.id as "Asset ID", ',
group_concat(
concat('max(case when ap.property_id = ',ap_id, ' then ap.', ap_data_type, '_value else null end) as "', ap_name,'",')
)
,' FROM chekrite_prod.equipment AS a JOIN chekrite_prod.asset_properties ap on ap.asset_id = a.id group by a.site_id, a.asset_id;'
)
from
(
SELECT i.id as ap_id, item as ap_name, asset_property_data_type as ap_data_type
FROM chekrite_prod.config_items as i
JOIN chekrite_prod.config_tables as t on t.id = i.table_id
WHERE t.company_id = 161 AND t.class = 'asset_property' ) a
)
;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END

Related

run prepared statement in fat-free framework

I need to run a following prepared statement query in fat-free framework.
I am trying to run the query as normal query.
public function weeklyLunchReport($date1=null, $date2=null)
{
$user = AclHelper::getCurrentUser();
$default_userID = intval($user['user_id']);
$defDate = new DateTime();
$default_date = $defDate->format('Y-m-d');
$date1 = (isset($date1) && $date1 != '') ? $date1 : $default_date;
$date2 = (isset($date2) && $date2 != '') ? $date2 : $default_date;
$sql =
"
SET #SQL = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN date = "',dt,'" THEN lunchStatus ELSE 0 END) AS "',dt,'"',
)
) INTO #SQL
FROM
(
SELECT DATE(issuedDateTime) as dt
FROM `lunch_status`
WHERE DATE(issuedDateTime) BETWEEN '$date1' AND '$date2'
) d;
SET #SQL
= CONCAT('SELECT userId, ', #SQL, '
FROM
(
SELECT userId, lunchStatus, DATE(issuedDateTime) as date
FROM `lunch_status`
WHERE DATE(issuedDateTime) BETWEEN '$date1' AND '$date2'
) as a
GROUP BY userId;');
PREPARE stmt FROM #SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
";
return $this->db->exec($sql);
}
But I know this isn't the right way.
Do I run it as stored procedure?
Put code in stored procedure and call it from F3, something like this:
$rows = $f3->get('DB')->exec("call my_stored_procedure($var1,$var2,...)");
This question doesn't relate directly to FFF, as it is a general question about what to do with complex SQL queries like yours.
I have had the same question myself (as I also have some weekly reports to run), and finally I have decided to keep the SQL query in the code, as you are doing. I didn't want to have it as a stored procedure, because I didn't want to rely on DB set up (it is not versioned). So as much as I hate it, I have some vanilla SQL code in my app too.
The question here maybe rather on how to test this kind of method. My advice is to put report related queries in a service initialized by a factory (factory is needed to return a service depending on the source of your data - for now it is SQL, but it can later change).

Debugging MySQL pivot row into dynamic number of columns

I recently came across the thread below, and it was very useful in building a dynamic SQL for MySQL.
MySQL pivot row into dynamic number of columns
With that said, I did struggle with trying to debug the statement. Now for the real purpose of this post! To debug, I would run a Select on my variable containing the statement (Select #SQL). Then copy that result from the viewer windows and have the query analyzer review it. Once I did this, development really sped up. I am sure this is known by all the advance pro developers but for any newbies, I hope this help!
My dynamic statement looks like this as a reference.
SET #sql = NULL;
SET ##group_concat_max_len = 50000;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
' sum(
case when symbol = ''',
symbol,
''' then pctttlassets end) AS ',
CONCAT(UPPER(ACode),'_',REPLACE(Symbol, '+', ''))
)
) INTO #sql
from trade_detail this;
SET #sql = CONCAT('SELECT Distinct(main.port_code) as PortCode, ', #sql, '
FROM trade_detail main GROUP BY main.Port_Code');
SELECT #SQL;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

MySQL / Mariadb - Select * from Stored Procedure

I am attempting to use UF Dashbuilder which adds syntax to my SQL query and I don't know how to correct it.
The call that works is similar to:
call database.report ('1234', 'txt');
Dashbuilder turns it into this which does not work:
SELECT * FROM (call database.report ('1234', 'txt');) AS `dbSQL` LIMIT 1
I could also use the code below from the end of the stored procedure to store the results in a table and then SELECT * FROM TABLE in Dashbuilder, but I don't know how to store the results in a table (dynamic number of columns).
Can you please tell me how I can make a stored procedure work with SELECT * added or how I can store the results from this code in a table?
SET #sql = NULL;
SET SESSION GROUP_CONCAT_MAX_LEN = 1000000; -- default is 1024
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(question = ''', REPLACE(question,"'", "\\'"), ''', answer, NULL)) AS ''', REPLACE(question,"'", "\\'"), ''''
)
) INTO #sql
FROM tmp2;
SET #sql = CONCAT('SELECT id, datestamp, ', #sql, ' FROM tmp2 GROUP BY id');
-- SELECT #sql;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
UPDATE 1.
COMMENTS TO ANSWER 1:
Results from original #SQL:
`SET #sql = CONCAT('SELECT id, datestamp, ', #sql, ' FROM tmp2 GROUP BY id');`
SELECT id, datestamp, MAX(IF(question = '1. Our records show that you got care from the provider named below in the last 6 months. {Provider}.  Is that right?', answer, NULL))
AS '1. Our records show that you got care from the provider named below in the last 6 months. {Provider}.  Is that right?',
MAX(IF(question = '2. Is this the provider you usually see if you need a check-up, want advice about a health problem, or get sick or hurt?', answer, NULL))
AS '2. Is this the provider you usually see if you need a check-up, want advice about a health problem, or get sick or hurt?',
MAX(IF(question = 'Area', answer, NULL)) AS 'Area',MAX(IF(question = 'Encounter', answer, NULL)) AS 'Encounter' FROM tmp2 GROUP BY id
Results from #SQL:
ERROR: Error Code: 1166. Incorrect column name '1. Our records show that you got care from the provider named below in the last 6 months. {Provider}'
I guess there is a character that it does not like such as the single quotes?
SET #tableName = 'myreport';
SET #sql = CONCAT('CREATE TABLE ', #tableName, ' AS SELECT id, datestamp, ', #sql, ' FROM tmp2 GROUP BY id');
CREATE TABLE myreport AS SELECT id, datestamp, MAX(IF(question = '1. Our records show that you got care from the provider named below in the last 6 months. {Provider}.  Is that right?', answer, NULL))
AS '1. Our records show that you got care from the provider named below in the last 6 months. {Provider}.  Is that right?',
MAX(IF(question = '2. Is this the provider you usually see if you need a check-up, want advice about a health problem, or get sick or hurt?', answer, NULL))
AS '2. Is this the provider you usually see if you need a check-up, want advice about a health problem, or get sick or hurt?',
MAX(IF(question = 'Area', answer, NULL)) AS 'Area',MAX(IF(question = 'Encounter', answer, NULL)) AS 'Encounter' FROM tmp2 GROUP BY id
UPDATE 2:
THIS WORKS!!! THANKS!
I have to reduce the length of the column name as shown below. Then I can run the stored procedure twice per day and select * from this table in Dashbuilder.
CREATE TABLE myreport AS SELECT id, datestamp, MAX(IF(question = '1. Our records show that you got care from the provider named below in the last 6 months. {Provider}.  Is that right?', answer, NULL))
AS '1.',
MAX(IF(question = '2. Is this the provider you usually see if you need a check-up, want advice about a health problem, or get sick or hurt?', answer, NULL))
AS '2.',
MAX(IF(question = 'Area', answer, NULL)) AS 'Area',MAX(IF(question = 'Encounter', answer, NULL)) AS 'Encounter' FROM tmp2 GROUP BY id
UPDATE 3: This works! Thanks!
SET #t = CONCAT('DROP TABLE IF EXISTS ', survey_report );
PREPARE stmt FROM #t;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #sql = NULL;
SET SESSION GROUP_CONCAT_MAX_LEN = 1000000; -- default is 1024
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(question = ''', REPLACE(question,"'", "\\'"), ''', answer, NULL)) AS ''', REPLACE(udf_clean_column_name(15, udf_remove_tags(question)),"'", "\\'"), ''''
)
) INTO #sql
FROM tmp2;
SET #sql = CONCAT('CREATE TABLE ', survey_report, ' AS SELECT id, datestamp, ipaddr, ', #sql, ' FROM tmp2 GROUP BY id');
-- SELECT #sql;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
DROP TEMPORARY TABLE IF EXISTS `survey_lookup`;
DROP TEMPORARY TABLE IF EXISTS `tmp`;
DROP TEMPORARY TABLE IF EXISTS `tmp2`;
Mysql Function to remove spaces, etc. from the column names.
CREATE FUNCTION `udf_clean_column_name`(col_name_len INT, str varchar(200)) RETURNS varchar(200)
BEGIN
SET str = SUBSTRING(str,1,col_name_len);
SET str = TRIM(str);
SET str = Replace(str,' ','_');
SET str = Replace(str,'-','');
SET str = Replace(str,'?','');
SET str = Replace(str,',','');
SET str = Replace(str,'.','');
RETURN str;
END;
Mysql function to remove tags (I don't recall where I got this function).
CREATE FUNCTION `udf_remove_tags`(Dirty varchar(4000))
RETURNS varchar(4000)
DETERMINISTIC
BEGIN
DECLARE iStart, iEnd, iLength int;
WHILE Locate( '<', Dirty ) > 0 And Locate( '>', Dirty, Locate( '<', Dirty )) > 0 DO
BEGIN
SET iStart = Locate( '<', Dirty ), iEnd = Locate( '>', Dirty, Locate('<', Dirty ));
SET iLength = ( iEnd - iStart) + 1;
IF iLength > 0 THEN
BEGIN
SET Dirty = Insert( Dirty, iStart, iLength, '');
set Dirty = Replace(Dirty,' ',''); #No space between & and nbsp;
set Dirty = Replace(Dirty,'\r','');
set Dirty = Replace(Dirty,'\n','');
END;
END IF;
END;
END WHILE;
RETURN Dirty;
END;
I don't see any mention of stored procedures in the UF DashBuilder documentation, so it looks like they don't have a way around this.
You can create a table from a SELECT query. If you omit the column specifications, they'll be derived automatically from the select list of the query.
SET #sql = CONCAT('CREATE TABLE ', tableName, ' AS
SELECT id, datestamp, ', #sql, ' FROM tmp2 GROUP BY id');
PREPARE stmt FROM #sql
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Mysql with parameters not working

I have a mysql stored procedure like this:
CREATE DEFINER=`root`#`localhost` PROCEDURE `accounts_summary_by`(
IN **created_by** int(10)
)
BEGIN
SET group_concat_max_len=2048;
SET #sql = NULL;
SELECT
GROUP_CONCAT(
DISTINCT CONCAT(
'MAX(IF(fiscal_year = ''',
fiscal_year,
''', amount, 0)) AS ',
CONCAT("'",fiscal_year,"'")
)
) INTO #sql
FROM
net_savings;
SET #sql = CONCAT('SELECT accounts.id,
accounts.account,
accounts.region,
accounts.cluster,
accounts.industry, ,'
,#sql,
'FROM net_savings join accounts
on accounts.id = net_savings.account_id
Where accounts.user_id = **created_by**
GROUP BY accounts.account,net_savings.account_id
ORDER BY accounts.id');
PREPARE statement FROM #sql;
EXECUTE statement;
DEALLOCATE PREPARE statement;
END
But upon calling the procedure like these:
CALL accounts_summary_by(2)
2 is a user_id reference to another table called users.
It gave me an error. Please help as I can't find any fixed to my problem.
0 72 23:41:12 CALL `buckets`.`accounts_summary_by`(1) Error Code: 1054. Unknown column 'created_by' in 'where clause' 0.000 sec
MySQL's internal programming language is not php, it is not going to resolve variables within a text, so you need to concat it properly to the middle of the prepared statement:
SET #sql = CONCAT('SELECT accounts.id,
accounts.account,
accounts.region,
accounts.cluster,
accounts.industry,'
,#sql,
'FROM net_savings join accounts
on accounts.id = net_savings.account_id
Where accounts.user_id ='
,created_by
,'GROUP BY accounts.account,net_savings.account_id
ORDER BY accounts.id');
Since created_by is a parameter of the procedure, you do not need to preposition it with #.

Execute statement only returns #Rows

I'm using PMA to test some pivot queries (dynamic columns), everything seems to be working just fine however, I'm only getting the # Rows in my results, not the actual set of rows.
How can I see my result set?
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(t.week_end = ''',
t1.week_end,
''', t.st_hours, NULL)) AS ''',
t1.week_end, '\''
)
) INTO #sql
FROM timesheets t1 WHERE t1.week_end > "2015-03-01";
SET #sql = CONCAT('SELECT t.assignment_id
, ', #sql, '
FROM timesheets t
LEFT JOIN timesheets t1 ON t.timesheet_id = t1.timesheet_id
GROUP BY t.assignment_id');
PREPARE stmt FROM #sql;
EXECUTE stmt;
Returns # Rows: 440
SELECT * FROM table - Returns the actual set of rows
This will be resolved in the latest PHPMyAdmin builds, and should be released in version 4.6.
[Prepared statements] can be sent in query as this pretty much works in phpMyAdmin right now. The only problem is displaying results. If you execute all of above, you get result just from last query (DEALLOCATE), which shows 0 rows, but if you do it without DEALLOCATE, you reportedly get 1 row, but it's not displayed.
Reference