DECLARE Error in My-sql Query - mysql

I am having query .Which i want to run on a phpmyadmin.
But whenever I run i got error at declare.
I am not able to find out what is the error in this ?
I want to run this block of code as a query from the PHP?
-- Declare a cursor to hold the section information for a specified product
DECLARE section_cursor CURSOR FOR
SELECT DISTINCT cds_especee.sectid, cds_evocee.text, min
(displayorder) displayorder
FROM cds_especee
JOIN cds_evocee ON (cds_especee.sectid = cds_evocee.id)
-- Replace the prodid below with a valid prodid from your data set
WHERE cds_especee.prodid = 'S1522339'
GROUP BY cds_especee.sectid, cds_evocee.text
ORDER BY displayorder ASC
OPEN section_cursor
-- Fetching the first section into variable
FETCH NEXT FROM section_cursor
INTO #section, #sectionname, #order
WHILE ##FETCH_STATUS = 0
BEGIN
-- Print current section to the screen
PRINT '******'+#sectionname+'******'
-- Declare a cursor to hold the header and body information for the
specified product
-- Note that the WHERE statement limits the results to the headers and body falling under the current section
DECLARE espec_cursor CURSOR FOR
SELECT evoc1.text, evoc2.text, displayorder
FROM cds_especee
JOIN cds_evocee evoc1 ON (cds_especee.hdrid = evoc1.id)
JOIN cds_evocee evoc2 ON (cds_especee.bodyid = evoc2.id)
-- Replace the prodid below with a valid prodid from your data set
WHERE cds_especee.prodid = 'S1522339' AND
cds_especee.sectid = #section
ORDER BY displayorder ASC
OPEN espec_cursor
-- Fetching the first header and body into variable
FETCH NEXT FROM espec_cursor
INTO #hdr, #body, #order1
WHILE ##FETCH_STATUS = 0
-- Below is a loop that prints all the headers and bodies for the
current section
BEGIN
PRINT #hdr +': '+#body
FETCH NEXT FROM espec_cursor
INTO #hdr, #body, #order1
END
-- Clear out the espec_cursor as it will be repopulated with data for
the next section as the procedure loops
CLOSE espec_cursor
DEALLOCATE espec_cursor
-- Fetches the next section and returns to the top of the loop
FETCH NEXT FROM section_cursor
INTO #section, #sectionname, #order
PRINT ' '
PRINT ' '
END
-- Clear out the section_cursor as the procedure is over
CLOSE section_cursor
DEALLOCATE section_cursor

Maybe is something about mysql delimiter. Try to run it like this:
DELIMITER $$
-- Declare a cursor to hold the section information for a specified product
DECLARE section_cursor CURSOR FOR
SELECT DISTINCT cds_especee.sectid, cds_evocee.text, min
(displayorder) displayorder
FROM cds_especee
JOIN cds_evocee ON (cds_especee.sectid = cds_evocee.id)
-- Replace the prodid below with a valid prodid from your data set
WHERE cds_especee.prodid = 'S1522339'
GROUP BY cds_especee.sectid, cds_evocee.text
ORDER BY displayorder ASC
OPEN section_cursor
-- Fetching the first section into variable
FETCH NEXT FROM section_cursor
INTO #section, #sectionname, #order
WHILE ##FETCH_STATUS = 0
BEGIN
-- Print current section to the screen
PRINT '******'+#sectionname+'******'
-- Declare a cursor to hold the header and body information for the
specified product
-- Note that the WHERE statement limits the results to the headers and body falling under the current section
DECLARE espec_cursor CURSOR FOR
SELECT evoc1.text, evoc2.text, displayorder
FROM cds_especee
JOIN cds_evocee evoc1 ON (cds_especee.hdrid = evoc1.id)
JOIN cds_evocee evoc2 ON (cds_especee.bodyid = evoc2.id)
-- Replace the prodid below with a valid prodid from your data set
WHERE cds_especee.prodid = 'S1522339' AND
cds_especee.sectid = #section
ORDER BY displayorder ASC
OPEN espec_cursor
-- Fetching the first header and body into variable
FETCH NEXT FROM espec_cursor
INTO #hdr, #body, #order1
WHILE ##FETCH_STATUS = 0
-- Below is a loop that prints all the headers and bodies for the
current section
BEGIN
PRINT #hdr +': '+#body
FETCH NEXT FROM espec_cursor
INTO #hdr, #body, #order1
END
-- Clear out the espec_cursor as it will be repopulated with data for
the next section as the procedure loops
CLOSE espec_cursor
DEALLOCATE espec_cursor
-- Fetches the next section and returns to the top of the loop
FETCH NEXT FROM section_cursor
INTO #section, #sectionname, #order
PRINT ' '
PRINT ' '
END
-- Clear out the section_cursor as the procedure is over
CLOSE section_cursor
DEALLOCATE section_cursor$$
DELIMITER ;

You cannot use many of those statements including DECLARE, OPEN, FETCH, CLOSE in a simple MySQL script. You should create a source object for this purpose. For example you could do it using stored procedure. There is a good example in the documentation - Cursors.
Also PRINT is not MySQL statement.

Related

Differentiate between no results returned and end of rows for cursor

I'm trying to implement a cursor in MYSQL. Inside that cursor, I have a select statement that might or might not return any rows.
I'm facing a problem when that query does not return any rows.
According to the MYSQL documentation,
NOT FOUND: Shorthand for the class of SQLSTATE values that begin with '02'. This is relevant within the context of cursors and is used to control what happens when a cursor reaches the end of a data set. If no more rows are available, a No Data condition occurs with SQLSTATE value '02000'. You can set up a handler for it or a NOT-FOUND condition to detect this condition. For another example, see Section 13.6.6, “Cursors”. The NOT FOUND condition also occurs for SELECT ... INTO var_list statements that retrieve no rows.
My termination of the cursor is implemented as usual.
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET FINISHED = 1;
The problem is that the termination is triggered because of the query inside the cursor returning 0 rows. Is there a way to differentiate between those two cases so that the cursor continues despite my query returning 0 results?
Thanks in advance.
DROP PROCEDURE IF EXISTS CURSOR_PLACEHOLDER;
DELIMITER $$
CREATE PROCEDURE CURSOR_PLACEHOLDER()
BEGIN
DECLARE FINISHED INTEGER DEFAULT 0;
DECLARE CURRENT_ROW_ID VARCHAR(256);
DEClARE CURRENT_ROW
CURSOR FOR
SELECT ID
FROM A
WHERE ID_P IN (SELECT ID_P
FROM A
GROUP BY ID_P
HAVING COUNT(ID_P) > 1);
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET FINISHED = 1;
OPEN CURRENT_ROW;
GET_ACTION:
LOOP
FETCH CURRENT_ROW INTO CURRENT_ROW_ID;
IF FINISHED = 1 THEN
LEAVE GET_ACTION;
END IF;
SET #CURRENT_P_ID := (SELECT ID_P FROM A WHERE ID = CURRENT_ROW_ID);
SELECT a.ID_U, a.ID_R, a.A, a.FROMDATE, a.TODATE
INTO #ID_U, #ID_R, #A, #FROM_DATE, #TO_DATE
FROM ASSIG a
WHERE a.ID_G = #CURRENT_P_ID; # <- Query that returns 0 rows and terminates the cursor
IF (#ID_U IS NOT NULL) THEN
SET #ASSIG_ID := GENERATE_ID();
INSERT INTO ASSIG
VALUES (#ASSIG_ID,
#G_ID,
#ID_U,
#ID_R,
#A,
#FROM_DATE,
#TO_DATE);
END IF;
UPDATE A
SET ID_P = #G_ID
WHERE ID = CURRENT_ROW_ID;
END LOOP GET_ACTION;
CLOSE CURRENT_ROW;
END
$$
DELIMITER ;

How to count values from the database table column?

I want to convert game tag data found here into a dimension table of a star schema.
But the problem is that steamspy_tag_data table is organised as such every column name is tag name of a game and one game can have multiple tags. For example, lets say I have game Warcraft3 with appid 30 it would be in a table like this.
appid|strategy|action|shooter|fantasy|
-----+--------+------+-------+-------
30 6345 1452 0 6340
Column value greater than 0 signifies amount of user votes that voted certain game to be of that game tag. For Warcraft3 game with appid 30 - 6345 users voted it classifies as strategy 1452 users it classifies as action, .. etc.
Some columns for example "abstract" (column) tag has almost all 0 throughout the whole column meaning almost no game uses that tag, so to simplify 372 columns with over 29k row value into something more compact I want to run a query that would count non-zero value per every tag column and put them in the new table "tagovi" for better visibility which columns(tags) have relatively low game usage count.
so far I came up with this:
CREATE DEFINER=`root`#`localhost` PROCEDURE `zbroji_tagove`()
BEGIN
DECLARE i INTEGER;
DECLARE total_row_count INTEGER;
DECLARE dummy VARCHAR(255);
DECLARE zbrojeno INTEGER;
DECLARE trenutna VARCHAR(255);
DECLARE kursor CURSOR FOR
SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_schema = 'sppi' AND table_name = 'steamspy_tag_data'
ORDER BY ordinal_position;
SELECT FOUND_ROWS() into total_row_count;
open kursor;
FETCH kursor into dummy;
SET i = 1;
ponavljanje: LOOP
IF i > total_row_count THEN
CLOSE kursor;
LEAVE ponavljanje;
END IF;
FETCH kursor INTO trenutna;
SET zbrojeno = 0;
SET zbrojeno = (SELECT COUNT(*) FROM steamspy_tag_data where trenutna <> 0);
INSERT INTO tagovi(kategorija,broj_igra)
VALUES (
(trenutna),(zbrojeno)
);
SET i = i + 1;
end LOOP;
END
New table tagovi has 3 columns (ID auto_increment, kategorija Varchar(255), broj_igra INTEGER).
When I execute my stored procedure "zbroji_tagove"() I get SQL ERROR CODE 1292; Truncated incorrect DOUBLE value 'some_tag_name'. So somehow sql treats variable value as value instead of column at line SET zbrojeno = (SELECT COUNT() FROM steamspy_tag_data where trenutna <> 0*);
Is there a way for me to accomplish what I want inside MySQL environment?
You can't use variables like that, you need a prepared statement
See
#sql = CONCAT("SELECT COUNT(*) INTO zbrojeno FROM steamspy_tag_data where ",trenutna," <> 0);";
PREPARE stmt1 FROM #sql;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;

Copy one column to another, two seperate tables

I want to copy all values from one column in table A to another column in table B. The column has 100+ rows. I tried this:
UPDATE nds_product_lang pl
SET description_short = (
SELECT product_supplier_reference
FROM nds_product_supplier ps
WHERE ps.id_product = pl.id_product);
But what it returns is
#1242 - Subquery returns more than 1 row
It returns the same error even if I remove the WHERE condition. What am I doing wrong?
Try this
UPDATE nds_product_lang pl, nds_product_supplier ps
SET pl.description_short = ps.product_supplier_reference
WHERE ps.id_product = pl.id_product
You can use a store procedure:
See below example
CREATE DEFINER=`xxx`#`localhost` PROCEDURE `additem`()
BEGIN
declare no_record int default 0;
declare mycat varchar(45) default ''; //variable data destination
declare mycursor CURSOR FOR // this point your source table
select field-name FROM yourtable;
declare continue handler for not found
set no_record = 1;
open mycursor;
add_item: LOOP
FETCH mycursor INTO mycat;
IF no_record = 1 THEN
LEAVE add_item;
END IF;
-- build email list
insert into dest_table values(val-field1,mycat, ect..);
END LOOP add_item;
close mycursor;
this work perfectly :-)

Check to see if tables are present in a database - stored procedure - MySQL

I want the user to input whatever database they want to check and whatever tables they want to check. For example the call would look like this:
call tableCheck('MyDatabase', 'table1 table20 table3')
So the procedure would check for those tables (space delimited). I have my code down below but I am having problem checking the other tables, it reads the first but not the second or third one. SO my code is not looping or not reading the next word.
PROCEDURE `tableCheck` (db VARCHAR(256), db_tables VARCHAR(256))
BEGIN
DECLARE tbl, tbls VARCHAR(256);
DECLARE c INT DEFAULT 0;
SET tbls = db_tables;
WHILE c = 0 DO
#split word
SET tbl = SUBSTRING_INDEX(tbls," ",1);
#go to next string
SET tbls = SUBSTR(tbls,LENGTH(tbl)+1);
#check every table
SELECT table_name AS 'Table Name'
FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema=db AND table_name=tbl;
IF tbls = 0 THEN
SET c = 1;
END IF;
END WHILE;
END
I have given this link out a few times today...so maybe it will work for you too.
Convert a delimited string to a list of values
Using the dbo.fnArray function from that link you should be able to join on the INFORMATION_SCHEMA.TABLES like this:
create procedure dbo.spCheckTable #db varchar(256), #tbls varchar(8000)
as
begin
select *
from INFORMATION_SCHEMA.TABLES i
inner join dbo.fnArray(#tbls, ' ') t on i.TABLE_NAME = t.arrValue
where i.TABLE_CATALOG = #db
end
Now its a stored procedure

Nested Cursor call is calling inner cursor only once in MYSQL

There are 2 procedures. When tested separately they execute fine.
When first SP calls 2nd SP, this is not called after the first call.
Please help resolve the issue.
First Cursor:
BEGIN
DECLARE vAttendEmpid,vNoOfDays, vempid INT DEFAULT 0;
DECLARE processed BOOLEAN DEFAULT FALSE;
DECLARE curEmp CURSOR FOR Select distinct empid as d1 from rawattendance where DATE_FORMAT( indatetime,'%m') = process_month and DATE_FORMAT( indatetime,'%Y') = process_year order by empid;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET processed = TRUE ;
OPEN curEmp;
loopemp: LOOP
FETCH FROM curEmp INTO vEmpid;
IF processed THEN
CLOSE curEmp;
LEAVE loopemp;
END IF;
--select vEmpid;
CALL sp_attendance(vEmpid,process_month,process_year);
END LOOP loopemp;
END
2nd Cursor.. Nested cursor
BEGIN
DECLARE vInDateTime, vOutDateTime,vTempInDateTime, vTempOutDateTime DATETIME ;
DECLARE vAttendEmpid ,vDiffHr INT DEFAULT 0;
DECLARE eprocessed BOOLEAN DEFAULT FALSE;
DECLARE curAttendance CURSOR FOR Select empid, indatetime ,outdatetime from rawattendance where empid=vEmpid and DATE_FORMAT( indatetime, '%m' ) = process_month and DATE_FORMAT( indatetime, '%Y' ) = process_year
order by indatetime;
OPEN curAttendance;
att_loop:LOOP
FETCH curAttendance INTO vAttendEmpid, vInDateTime,vOutDateTime;
select concat ('In Time 0 ==',vInDateTime, ' out ==', vOutDateTime, ' Empid=',vAttendEmpid);
select 'looping';
IF eprocessed THEN
select 'loop end';
select concat ('In Time 4 ==',vTempInDateTime, ' out ==', vTempOutDateTime, ' Empid=',vAttendEmpid);
SET vDiffHr =TIMESTAMPDIFF(HOUR,vTempInDateTime,vTempOutDateTime);
insert into emp_attendance_processed(empid,in_date_time, out_date_time, workedhr)
values(vAttendEmpid,vTempInDateTime,vTempOutDateTime, vDiffHr);
SET vTempOutDateTime=vOutDateTime;
CLOSE curAttendance;
END IF;
END LOOP att_loop;
END
Try to reset your continue handler variable processed after the inner procedure is called.
SET processed = FALSE;
The Problem is that the HANDLER FOR NOT FOUND is not only executed if the cursor in your first procedure returns no rows, but also if a nested SELECT returns no rows. And as your second procedure contains SELECT statements, I believe one of them is returning an empty set at least one time. If that's not intended, it may have to do with faulty parameters assigned.
OPEN curEmp;
loopemp: LOOP
FETCH FROM curEmp INTO vEmpid;
IF processed THEN
CLOSE curEmp;
LEAVE loopemp;
END IF;
--select vEmpid;
CALL sp_attendance(vEmpid,process_month,process_year);
SET processed = FALSE;
END LOOP loopemp;