MySQL Use table name for function - mysql

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.

Related

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?

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

MySql quick user select

I have a Users table and I'm getting user details (usual way) with id.
This is how I'm getting user details;
select id,kullaniciadi,FotoGet(K.Foto,K.Gender) from kullanicilar K where id=1;
FotoGet function always returning string value like 'Photos/ssss.jpg'
So far I have not trouble to use this way but I'm wondering how can I do this with a single function?
Like
set #uid=1;
Select UserGet(#uid);
I will put the id inside parentheses and the function will run my select query and return all user detail columns. id, kullaniciadi, FotoGet(K.id,K.Foto,K.Gender)
Can I use this way to get details?
A MySQL stored function cannot return multiple columns, it can only return a single scalar value.
But you could design a stored procedure that returns a result set:
CREATE PROCEDURE UserGet(uid INT)
SELECT id, kullaniciadi, FotoGet(K.Foto,K.Gender) FROM kullanicilar K WHERE id=uid;
Then call it like so:
CALL UserGet(1234);
It returns a result set just like a SELECT query would.
DELIMITER //
CREATE PROCEDURE UserGet(IN uid INT, IN column_name VARCHAR(64))
BEGIN
SET #sql = CONCAT('SELECT id, ', column_name, ' FROM kullanicilar K WHERE id=?');
PREPARE stmt FROM #sql;
SET #uid = uid;
EXECUTE stmt USING #uid;
END//
DELIMITER ;
Call it like so:
CALL UserGet(1234, 'kullaniciadi');
Remember that it's your responsibility to write code to pass a valid column name as the procedure argument. If you allow untrustworthy content to be passed, then it might be an SQL injection vulnerability.
Re your additional comment:
This should work fine:
CALL UserGet(1234, 'FotoGet(Foto,Gender)');

MySql Stored Proc - Select query returns null if using where clause not included in select list?

I have a proc that simply contains the following:
SELECT Col1, Col2 FROM table WHERE Id = 1;
This always returns null values. If I change the statement to:
SELECT Id, Col1, Cold2 FROM table WHERE Id = 1;
The row gets returned as expected. Does mySql procs demand that the where clause columns appear in the select list? It doesn't have this behaviour when running the SQL directly in phpMyAdmin.
Here's the code in question:
CREATE PROCEDURE sp_player_login
(
IN
userGraphId INT(11),
authToken TEXT
)
BEGIN
DECLARE playerId INT;
DECLARE newPlayer BOOLEAN DEFAULT FALSE;
SELECT Id INTO playerId FROM player WHERE FacebookGraphId = userGraphId;
If playerId IS NULL THEN
-- Create the player.
SET newPlayer = TRUE;
-- Get new player defaults.
SELECT NewPlayerTurns, NewPlayerMoney, NewPlayerMorale, NewPlayerMissilePower FROM defaults WHERE Id = 1;
END IF;
END #
The second SELECT NewPlayerTurns... is the one that returns null values if I don't specify the Id column in the select clause. If I remove the first SELECT Id INTO ...the second query works without the Id in the select clause...? confused

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