mysql - calling stored procedure inside another stored procedure - mysql

Since mysql functions cannot return tables/result sets therefore i created a stored procedure (Get_StudentsWithAllIndicators) that does the stuff i needed. Now, i need to use this stored procedure result inside the actual stored procedure(Find_MapDetails) like this.
select * from students where studentid in (Get_StudentsWithAllIndicators('7,8', 2));
but it does not work! If you are recommending creating a temporary table and insert values into it please tell me the syntax..thanks
Get_StudentsWithAllIndicators
CREATE PROCEDURE `Get_StudentsWithAllIndicators`(IN p_list VARCHAR(255), IN p_length int)
BEGIN
/*make query with the length of indicators in the list*/
DECLARE x INT;
SET x=1;
SET #queryMain = 'SELECT distinct studentid FROM studentindicators WHERE studentid IN ';
SET #queryWhere = '(SELECT studentid FROM studentindicators WHERE indicatorid = substring_index(\'';
SET #query = '';
WHILE x <= p_length DO
SET #query = CONCAT(#query, #queryWhere, p_list, '\', ",", 1)) AND studentId IN ');
SET x=x+1;
SET #lengthWithCommas = Length(p_list);
SET p_list = substr(p_list, instr(p_list, ',') + 1, #lengthWithCommas - instr(p_list, ','));
END WHILE;
/*remove last AND - note: no occurence of A after AND is expected*/
SET #query = CONCAT(#queryMain, LEFT(#query, LENGTH(#query) - LOCATE('A', REVERSE(#query))));
PREPARE stmt FROM #query;
EXECUTE stmt;
END

INSERT INTO #MYTEMPTABLE exec Get_StudentsWithAllIndicators('7,8', 2)
SELECT * FROM students where studentId in (SELECT studentid FROM #MYTEMPTABLE)
Save the results of the first sp into a temp table.

Related

how to make multiple LIKE AND statements inside stored procedured?

For example, I got an array :
carBrand: 'ford','volve','honda'
I would like to search a field which contained all elements of it, just like :
SELECT * FROM car_company WHERE car_company.brandStory LIKE '%ford%' AND car_company.brandStory LIKE '%volve%'
AND car_company.brandStory LIKE '%honda%';
And the array is an input parameter outside stored procedure
So far, I got two approachs nearly but still not good to me:
use REGEXP
for example:
SET carBrand = 'ford|volve|honda'; //input parameter
SELECT * FROM car_company WHERE car_company.brandStory REGEXP carBrand;
But the code make the OR statement actually, all I want is AND statement.
use full-text index
for example:
SET carBrand = '+ford +volve +honda'; //input parameter
SELECT * FROM car_company WHERE MATCH (brandStory) AGAINST (carBrand IN BOOLEAN MODE);
This is the closest solution I have found,but I really don't want to set the full-text index.
Is there any other solution ? Thanks everyone !
This stored procedure
USE `testdb`;
DROP procedure IF EXISTS `BuildSelect`;
DELIMITER $$
USE `testdb`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `BuildSelect`(IN carbrand TEXT)
BEGIN
DECLARE brand TEXT DEFAULT NULL;
DECLARE brandlength INT DEFAULT 0;
DECLARE Tempbrand TEXT DEFAULT NULL;
SET #Selectstr = "SELECT * FROM car_company WHERE";
iterator:
LOOP
IF LENGTH(TRIM(carbrand)) = 0 OR carbrand IS NULL THEN
LEAVE iterator;
END IF;
SET brand = SUBSTRING_INDEX(carbrand,',',1);
SET Tempbrand = CONCAT(" car_company.brandStory LIKE '%",TRIM(brand),"%'");
IF brandlength > 0 THEN
SET Tempbrand = CONCAT(" AND",Tempbrand);
END IF;
SET #Selectstr = CONCAT(#Selectstr,COALESCE(Tempbrand,''));
SET carbrand = SUBSTRING_INDEX(carbrand,',',-(LENGTH(carbrand) - LENGTH(REPLACE(carbrand, ',', '')) ));
SET brandlength = brandlength +1;
END LOOP iterator;
SET #Selectstr = CONCAT(#Selectstr ,";");
PREPARE id FROM #Selectstr;
EXECUTE id;
DEALLOCATE PREPARE id;
#SELECT #Selectstr;
END$$
DELIMITER ;
Would run with this call
call BuildSelect('Ford,Audi,Mercedes');
Run this query
SELECT * FROM car_company
WHERE car_company.brandStory LIKE '%Ford%'
AND car_company.brandStory LIKE '%Audi%'
AND car_company.brandStory LIKE '%Mercedes%';

how to handle \ in query mysql

I have a procedure in which I am making query as string then prepare query and execute.
Here is the procedure
CREATE DEFINER=`root`#`%` PROCEDURE `dim_add_customer`(
IN _customer_id BIGINT(20) ,
IN _first_name VARCHAR(50) ,
)
BEGIN
SET #_query := CONCAT('first_name = "',_first_name,'"');
SET #_query := CONCAT('UPDATE customer_detail SET ',#_query,' WHERE customer_id = ',_customer_id);
PREPARE stmt FROM #_query;
END$$
DELIMITER ;
Now when I call
call dim_add_customer(1,'abc\\')
Then there is issue in creating string query.The query it made
UPDATE customer_detail SET first_name = "abc\" WHERE customer_id = 1
is there any best solution to solve this ?
You shouldn't build the queries by concat.
You should use the parameters in the query like
SET #_query="UPDATE customer_detail
SET first_name=#_first_name
WHERE customer_id = #_customer_id"
I'm not sure if you can declare your variables directly from the input parameters like
CREATE DEFINER=`root`#`%` PROCEDURE `dim_add_customer`(
IN #_customer_id BIGINT(20) ,
IN #_first_name VARCHAR(50) ,
)
or you have to
SET #_customer_id = _customer_id
SET #_first_name = _first_name
CAVEAT: I'm used to the MsSql-way of creating procedures with variables; I might have misunderstood something, but at least creating sql by concat should be your last resort.
Creating queries by concat is the equivalent of
x=1
q=concat("y=",x,"+2")
eval (q)
instead of
x=1
y=x+2

Check MySQL database for unique value over many tables

I'm looking for a way to easily check each table of a MySQL database and make sure that a certain field contains one value only. I have tables named Authors, Titles, Places, etc.
Each table contains a field called xuser and it needs to ask "does the field xuser contain the value xy in all records of all tables".
Can someone push me in the right direction how to do this with a SQL query if this is possible?
Thanks for reading, regards
Nico
I've created stored procedure which checks all table for provided db:
DELIMITER $$
DROP PROCEDURE IF EXISTS `UTL_CHECK_BACKUP_FOR_USER` $$
CREATE PROCEDURE `UTL_CHECK_BACKUP_FOR_USER`(
IN i_database_name VARCHAR(255),
IN i_user_column_name VARCHAR(255),
IN i_user_column_value VARCHAR(255),
OUT o_result TINYINT(1)
)
BEGIN
DECLARE v_table_name VARCHAR(255);
DECLARE v_last_row_fetched TINYINT(3) DEFAULT 0;
DECLARE tables_cursor CURSOR FOR
SELECT table_name
FROM information_schema.tables
WHERE table_schema = i_database_name
;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_last_row_fetched = 1;
SET v_last_row_fetched = 0;
OPEN tables_cursor;
SET #query =
CONCAT(
'SELECT SUM(IF(user_column=''',
i_user_column_value,
''', 1, -1)) = 1 INTO #o_result FROM ( SELECT ''test'' AS user_column FROM information_schema.tables WHERE 1<>1 '
)
;
table_loop: LOOP
FETCH tables_cursor INTO v_table_name;
IF (v_last_row_fetched = 1) THEN
LEAVE table_loop;
END IF;
SET #query =
CONCAT(
#query,
' UNION SELECT DISTINCT(',
i_user_column_name,
') AS user_column FROM ',
v_table_name
)
;
END LOOP table_loop;
CLOSE tables_cursor;
SET v_last_row_fetched=0;
SET #query =
CONCAT(
#query,
' ) all_xusers;'
)
;
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET o_result = COALESCE(#o_result, 0);
END $$
DELIMITER ;
Just deploy this stored procedure to database.
And then it could be executed in the following way:
-- db_name, user_column_name, user_column_value, result
call UTL_CHECK_BACKUP_FOR_USER('test', 'xuser', 'xxx', #result);
select #result;
To get the rows from all three tables where xuser has the same value in all three tables you could use:
SELECT *
FROM authors a
JOIN titles t
ON t.xuser = a.xuser
JOIN places p
ON p.xuser = t.xuser
If you want to look at a specific xuser value you could add the following WHERE clause:
WHERE a.xuser = 'xy'
The first thing comes to my mind:
select sum(if(xuser='xxx', 1, -1)) = 1
from (
select distinct(xuser) from authors
union
select distinct(xuser) from titles
union
select distinct(xuser) from places
) all_xusers;
This will return 1 (true) if all tables contains records belonging ONLY to 'xxx' user. Otherwise (if there is no 'xxx' records or there is some other user records) it will return 0 (false).

How to fetch last select statements result set?

I have a stored procedure that looks like below Pseudo:
create procedure composite(IN a varchar(255),IN b varchar(255),IN c datetime,IN d datetime)
begin
DECLARE str VARCHAR(255);
DECLARE count float;
SET str = '';
SET str = CONCAT("aname like '%",a,"%' "," and bname ='",b,"' ");
set #comp = CONCAT("SELECT * from abc where ",str, "GROUP BY qname");
PREPARE stmt FROM #comp;
EXECUTE stmt;
set count = found_rows();
SET STR1 = CONCAT("aname like '%",a,"%' "," and bname ='",b,"' ");
SET #sql = CONCAT("SELECT * from xyz",str,"GROUP BY DATE(FROM_UNIXTIME(abcdate)),qname");
PREPARE stmt FROM #sql;
EXECUTE stmt;
end//
When I execute this i get 2 result-sets as output i.e. from executing 2 select statement. I want the output of only last select. Is there any way to do this?
Do not quite understand what you want to do. I imagine that the stored procedure is not complete.
Is it really necessary to use prepared statements in this case? Do you need to count as float?
Maybe something like this might be useful:
...
DECLARE count BIGINT UNSIGNED;
SELECT COUNT(*) INTO count /* Here you can use a user variable (#count) and avoiding the local variable (count) */
FROM (
SELECT 0
FROM abc
WHERE aname LIKE CONCAT('%', a, '%') AND bname = b
GROUP BY qname
) der;
SELECT aname, bname, qname
FROM xyz
WHERE aname LIKE CONCAT('%', a, '%') AND bname = b
GROUP BY qname;
...
The first statement will store the number of rows in the local variable count and will not return the dataset. Beware of variable names and reserved words, in this case count is allowed, but read 9.3. Reserved Words in the documentation.

Dynamic insert into variable table statement SQL Server

I have a variable table:
DECLARE #A_Table TABLE(ID INT, att1 VARCHAR(100), att2 nvarchar(200))
I want to make dynamic sql, so I insert into this table some data (all inside a loop):
WHILE (#i <= 100) BEGIN
SELECT #other_att = NAME FROM #other_Table where ID = #i;
SET #sql = 'INSERT ' + #A_Table+ '(ID,att1,att2) SELECT '+CAST(#i AS VARCHAR)+' , '''+ #other_att+''', SUM('+ #other_att') FROM '+ #EVEN_OTHER_Table;
EXEC (#sql);
END
sql every time would look like:
INSERT INTO #A_Table SELECT 1 , 'subject', SUM(subject)
INSERT INTO #A_Table SELECT 2 , 'age', SUM(age)
INSERT INTO #A_Table SELECT 3 , 'sex', SUM(sex)....
AND after executing this :
SO I will get:
#A_Table:
id att1 att2
1 subject 4.3
2 age 4.5
3 sex 4.1
but I get an error:
Msg 137, Level 16, State 1, Line 48
Must declare the scalar variable "#A_Table".
SO what is it the syntax to insert dynamically into a variable table?
Ok I have understood it.
You could use the INSERT ... EXEC syntax to insert the data returned by the dynamic SELECT. Of course, you would then need to remove the INSERT part from the dynamic statement.
WHILE (#i <= 100) BEGIN
SELECT #other_att = NAME FROM #other_Table where ID = #i;
SET #sql = 'SELECT '+CAST(#i AS VARCHAR)+' , ''' + #other_att+''', SUM('+ #other_att + ') FROM '+ #EVEN_OTHER_Table;
INSERT INTO #A_Table (ID,att1,att2)
EXEC (#sql);
END
You have a table variable, not a variable that contains the table name.
So you would need the following.
WHILE (#i <= 100) BEGIN
SELECT #other_att = NAME FROM #other_Table where ID = #i;
SET #sql = 'INSERT INTO #A_Table (ID,att1,att2) SELECT '+CAST(#i AS VARCHAR)+' , '''+ #other_att+''', SUM('+ #other_att') FROM #EVEN_OTHER_Table';
EXEC (#sql);
END
You would also need to declare the table variable as a statement inside the #sql variable, and execute your declare table and inserts together, or use a local/global temporary table.
With a local temporary table (stored in the tempdb) you could do something like this.
CREATE TABLE #testtbl (ID INT);
EXEC ('INSERT INTO #testtbl VALUES (1)');
SELECT * FROM #testtbl
DROP TABLE #testtbl
Some good info about temporary tables in BOL
http://msdn.microsoft.com/en-us/library/ms174979.aspx - quite far down the page
And the table type.
http://msdn.microsoft.com/en-us/library/ms175010.aspx
Your EXEC statement occurs in a different context and is therefore unaware of any variables created in your original context.
To create dynamic insert query it is really a task, I also struggle to find it ,finally I have tried in the following way and it's successfully working. Please find the code below.
CREATE PROCEDURE [dbo].[InsertTodaysData] (#tbl varchar(50),#Days int,
#MDate varchar(50), #EValue varchar(50), #Speed varchar(50),
#Totalreturn varchar(50),#Closingv varchar(50), #TotalReturnV varchar(50))
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #SQLQuery varchar(2000)
-- Insert statements for procedure here
set #SQLQuery = 'INSERT INTO '+#tbl+' (ID,MDate,EValue,Speed,TotalReturnRatio,ClosingValue,
TotalReturnValue) VALUES ('+#Days+','''+#MDate+''', '+#EValue+', '+#Speed+',
'+#Totalreturn+', '+#Closingv+', '+#TotalReturnV+')'
EXECUTE(#SQLQuery)
END
Hope this will help you..