how to handle \ in query mysql - 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

Related

Unknown column ' ' in the field list mysql and passing dynamic table name while calling mysql function

I was trying to create a mysql stored procedure function using mysql workbench, which will show result of join data of two tables on based on some conditions. I want to pass table names as parameter also.
My code is here:
CREATE PROCEDURE `Get_Texts`(IN wrd longtext, IN dbname longtext,
IN splitdbname longtext,
IN lang longtext)
BEGIN
SET #sql_ = CONCAT('SELECT * FROM ',dbname,' as ifxcd
INNER JOIN
',splitdbname,' as ifxsd
ON
ifxsd.Crawl_id = ifxcd.Id where ifxsd.Language = ',lang,'
AND ifxsd.Word Like ',wrd,'%
order by ifxsd.Percentage desc
limit 100');
PREPARE statement_ FROM #sql_;
EXECUTE statement_ ;
END
Call Function:
call Get_Texts('acc', emp_info, split_emp_txt , 'English(en)');
After calling the function I get an error
'Unknown column 'emp_info' in the field list
How can I overcome this and can see the desired output? Thanks in advance.
SET a udv before the call and prefix emp_iinfo with an at symbol. same for split_emp_text
for example
set #emp_info = 'aaa';
set #split_emp_text = 'bbb'
call Get_Texts('acc', #emp_info, #split_emp_txt , 'English(en)');
The problem is in syntax of the query as i found finally. Here is the correct code:
CREATE PROCEDURE `Get_Texts`(IN wrd longtext, IN dbname longtext,
IN splitdbname longtext, IN lang longtext)
BEGIN
SET #sql_ = CONCAT("SELECT * FROM `",dbname ,"` as ifxcd
INNER JOIN `",splitdbname,"` as ifxsd ON ifxcd.id = ifxsd.Crawl_id
where ifxsd.Language = '",lang,"' and ifxsd.Word Like '",wrd,"%'
ORDER BY ifxsd.percentage DESC
limit 100");
PREPARE statement_ FROM #sql_;
EXECUTE statement_ ;
DEALLOCATE PREPARE statement_;
END
Call Procedure:
call Get_Texts('acc', 'emp_info', 'split_emp_txt' , 'English');

why mysql procedure return null

I have a simple mysql procedure which must return an query string. But, it returns almost every time QueryResult (column name) as <null> value.
create procedure return_table_rename_query(
IN targetTable VARCHAR(100),
IN tblPrefix VARCHAR(100)
)
BEGIN
SET #returnQuery = CONCAT('SELECT "MYSQLIMPORT can not rename table for target ', #targetTable, '";');
SET #totalRows = (SELECT COUNT(*) FROM table);
if IFNULL(#totalRows, 0) > 0
then
SET #returnQuery = CONCAT('drop table if exists table_name.', ...);
end if;
SELECT #returnQuery AS 'QueryResult';
end;
#targettable is not the same variable as targettable - you are mixing user defined variables and parameter variables and it seems likely that #targettable is null and if any element in a concat is null then the result is null.
Please read How to declare a variable in MySQL?

MySQL Use table name for function

When we use a statement like select count(*) from TABLE, the function count() automatically knows which table it is counting. Is it possible to grab the table and use it in a user defined function.
drop function if exists related_count;
create function related_count(parent int(11)) returns int(11) deterministic
begin
declare count int(11) default 0;
set count=(select count(*) from TABLENAME where id=parent);
return count;
end;
So that I can use it like this:
select count(*),related_count(id) from TABLENAME
So that I can use the same function regardless of table instead of defining multiple functions because of multiple tables.
Is there a way to switch between select count(*) from TABLENAME1 where id=parent or select count(*) from TABLENAME2 where id=parent dependent on a variable related_count('TABLE1',id)
The comment above from #RajeevRanjan mentions using dynamic SQL. This won't work, but if it did it would look like this:
create function related_count(tablename varchar(64), parent int) returns int reads sql data
begin
declare count int default 0;
set #sql = concat('select count(*) into count from `', tablename, '` where id = ', parent);
prepare stmt from #sql;
execute stmt;
return count;
end
However, this is not allowed:
ERROR 1336 (0A000): Dynamic SQL is not allowed in stored function or trigger
The reason it doesn't work is that your stored function could be called by an expression in an SQL statement that is itself a dynamic SQL execution. I guess MySQL only allows one level "deep" of prepare/execute. You can't make a prepared query run another prepared query.
To do this, you'd have to hard-code each table name like the following:
create function related_count(tablename varchar(64), parent int) returns int reads sql data
begin
declare count int default null;
if tablename = 'foo' then set count = (select count(*) from foo where id = parent);
elseif tablename = 'bar' then set count = (select count(*) from bar where id = parent);
elseif tablename = 'baz' then set count = (select count(*) from baz where id = parent);
end if;
return count;
end
This also has an advantage that it isn't an SQL injection vulnerability, whereas the PREPARE/EXECUTE solution (if it had worked) would be.
PS: A function that reads from other tables is not deterministic.

MySQL turn a JOIN statement into a Stored Procedure or Function?

So I have a JOIN statement that I will be using in multiple places. It essentially finds an IP address and matches it to said location from the intermediate table. I need to pass in two variables - one being the prefix of my database/schema and the other being the IP Address itself.
Therefore used is the CONCAT() function in order to piece it together.
So at the moment I have a procedure that looks something like this:
CREATE DEFINER=`root`#`%` PROCEDURE `LocationFromIp`(
ipAddress VARCHAR(16),
clientComp VARCHAR(32)
)
BEGIN
DECLARE test VARCHAR(255);
SET #networkSql = CONCAT("
SET #Location =
(SELECT `network`.`Name`
FROM `", clientComp, "-settings`.`iptable` AS `iptable`
LEFT JOIN `", clientComp, "-settings`.`network` AS `network`
ON `network`.`Subnet` = `iptable`.`Subnet`
WHERE `iptable`.`IP` = '", ipAddress, "'
LIMIT 1);
");
PREPARE test1 FROM #networkSql;
EXECUTE test1;
SELECT #Location AS `Location`;
It returns the result I want however I don't know how I can use this in a statement.
SELECT `IPAddress` AS CALL LocationFromIp('clientComp', `IPAddress`)
(
SELECT `IPAddress`
FROM `clientComp-data`.`tablename`
WHERE #date > `Date`;
)
GROUP BY `IPAddress`
The above does not work but I hope you can understand my thinking!
So how would I do it?
Why can't you adjust your stored procedure to include all the fields that you need from the very beginning?

How to pass list of items as parameter to a stored procedure

I have a stored procedure
create PROCEDURE [dbo].[SP]
(
#OrderList varchar(500)
)
AS
Begin
select *
from table
where id in ('+ #OrderList +')
Here I am passing orderlist....
When I execute like this
exec sp 'iss005,iss006'
I am not getting data
but when I hardcode in sp like this ...
select * from table where id in ('iss005','iss006')
then am getting data...
Thank you
Unfortunately it won't work that way. If you change your procedure to something like the following, this will work:
Create Procedure dbo.SP
#OrderList varchar(500)
AS
Declare #SQL VarChar(1000)
Select #SQL = 'SELECT * FROM table '
Select #SQL = #SQL + 'WHERE id in (' + #OrderList +')'
Exec ( #SQL)
GO
Looking more into your query, your ID's value varchar, so the procedure will fail as you'll still be getting :
WHERE id in (iss005,iss006)
when you want :
WHERE id in ('iss005','iss006')
You would need to either pass in the quote values, e.g. :
#OrderList = 'iss005','iss006'
Or work out some SQL to split the #OrderList by comma and use the QUOTENAME() function to add the quotes to the new variable.
I strongly recommend in this case the use of XML parameters, will give you a lot of flexibility.
Your XML might be something like
<ids>
<id>iss006</id>
<id>iss005</id>
</ids>
Your procedure should be something like this:
create PROCEDURE [dbo].[SP]
(
#OrderList XML
)
AS
Begin
select * from table
where id in (
select ParamValues.ID.value('.','VARCHAR(50)')
FROM #OrderList.nodes('/ids/id') as ParamValues(id)
)
Besides the use of store procedures outputs I also would recommend the use of functions but that is up to you.
Regards.
I had the same kind of requirement. i was getting list of user in a int list variable and i need to get all the order of those user. I have use a very simple trick which had solve my issue. please find the code.
public DataTable GetAllOrderData(List<int> UserID)
{
try
{
string listofuser = String.Join(",", UserID.ToArray());
SqlParameter[] parameters = new SqlParameter[]
{
new SqlParameter("#USERID", listofuser)
};
return SqlDBHelper.ExecuteParamerizedSelectCommand("GetOrderByUserID", System.Data.CommandType.StoredProcedure, parameters);
}
finally { UserID = null; }
}
And this is the stored procedure
CREATE PROCEDURE [dbo].[GetOrderByUserID] (#USERID varchar(700))
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Declare #SQL VarChar(1000)
Select #SQL = 'SELECT *,ORM.OrganisationName FROM OrderTransaction ORT LEFT JOIN OrganisationMaster ORM ON (ORT.OrganisationID=ORM.OrganisationID) '
Select #SQL = #SQL + 'WHERE ORT.CreatedBy IN (' + #USERID +')'
Exec ( #SQL)
END