mysql char displaying just the first character - mysql

I have this value in my MYSQL table "&#84&#101&#115&#116 " (=="Test")
this text is basically in decimal format.
more info: https://en.wikipedia.org/wiki/T#Computing_codes
i am trying to run a select query as its a regular text.
these are the tests i'm running:
1.
query:
select TRIM(Leading ',' FROM replace(trim(name),"&#",",")) from table where id = 1;
output:
84,101,115,116
2.
query:
select char(84,101,115,116);
output: Test
3.
query:
select char(TRIM(Leading ',' FROM replace(trim(name),"&#",","))) from table where id = 1;
output: T
How can i get the whole word instead of just the first character?
Thanks,
Nir.

you are not getting expected result because
TRIM(Leading ',' FROM replace(trim(name),"&#",","))
returns string instead of array
'84,101,115,116'
Then char() only interprets first readable set of numbers.
If you want to continue, take a look at similar question made with procedures.
You should create a procedure that would return string decimals as a table result set and then use it as input to your CHAR(). This way you would move complicated logic to procedure and then use it like this (untested):
select
GROUP_CONCAT(
SELECT
char(*)
FROM
(
CALL database.getDecimalText()
)
) SEPARATOR '' )
from
table
where
id = 1;

As stated by Mulcek, your passing what looks like comma separated arguments to the CHAR function, but this is in fact a single string that contains commas. MySQL interprets it as such and returns the decoded first number it recognises.
A one step solution would be to use a prepared statement to build the whole query as a string and then execute that as follows:
SET #VTestVar = '&#84&#101&#115&#116';
SET #VExec = CONCAT('SELECT CHAR(', (SELECT TRIM(Leading ',' FROM REPLACE(TRIM(#VTestVar),"&#",","))), ') value;');
PREPARE stmt FROM #VExec;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Here it is adjusted for your use case:
SET #VTestVar = '&#84&#101&#115&#116';
SET #VExec = CONCAT('SELECT CHAR(', (SELECT TRIM(Leading ',' FROM REPLACE(TRIM(select TRIM(Leading ',' FROM replace(trim(name),"&#",",")) from table where id = 1),"&#",","))), ') value;');
PREPARE stmt FROM #VExec;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Regards,
James

Related

MySQL - create a table with all of the fields that two tables have [duplicate]

I have to convert a MSSQL stored proc that passes a varchar that is a query:
INSERT INTO Results
EXEC (#Expresion);
This isn't working. I'm pretty sure that EXEC and EXECUTE aren't MySQL commands, but CALL doesn't work either.
Does anyone know if it's even possible to have something like JavaScript's eval function for MySQL?
I think you're looking for something like this:
SET #queryString = (
SELECT CONCAT('INSERT INTO user_group (`group_id`,`user_id`) VALUES ', www.vals) as res FROM (
SELECT GROUP_CONCAT(qwe.asd SEPARATOR ',') as vals FROM (
SELECT CONCAT('(59,', user_id, ')') as asd FROM access WHERE residency = 9
) as qwe
) as www
);
PREPARE stmt FROM #queryString;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #asd = NULL;
This is the SQL equivalent of eval(my_string);:
#Expression = 'SELECT "Hello, World!";';
PREPARE myquery FROM #Expression;
EXECUTE myquery;
Basically I combined the existing answers, neither tells you how to do eval exactly.
If you want to add parameters, you can use this:
#username = "test";
#password = "asdf";
#Expression = 'SELECT id FROM Users WHERE name = ? AND pass = ?;'
PREPARE myquery FROM #Expression;
EXECUTE myquery USING #username, #password;
And to answer the original question exactly:
#Expression = 'SELECT "Hello, World!";'
PREPARE myquery FROM #Expression;
INSERT INTO Results
EXECUTE myquery;
Note that the PREPARE ... FROM statement wants a session variable (prefixed with #). If you try to pass a normal variable, it will throw its hands up in the air and it just won't care.
EXECUTE is a valid command in MySQL. MySQL reference manual
The EXECUTE MySQL command can only be used for one prepared statement.
If case you want to execute multiple queries from the string, consider saving them into file and source it, e.g.
SET #query = 'SELECT 1; SELECT 2; SELECT 3;';
SELECT #query INTO OUTFILE '/tmp/temp.sql';
SOURCE /tmp/temp.sql;

MySQL GROUP_CONCAT 'Invalid use of Group function' error that DOESN'T involve an aggregate function

I have a MySQL stored procedure (shown below) that's supposed to build a list of IDs from a table of hierarchically related records. I'm having to re-engineer an older stored procedure to switch from using a simple CONCAT function to GROUP_CONCAT because the former couldn't handle the sizes of the lists being generated (i.e., the lists are going well over the 1024 character limit of the CONCAT function).
DELIMITER $$
CREATE PROCEDURE SPTest (top_id INT)
BEGIN
DECLARE ids_all TEXT;
SET SESSION group_concat_max_len = 1000000;
SET ids_all = top_id;
SET #str = GROUP_CONCAT('SELECT GROUP_CONCAT(id SEPARATOR \', \') ',
'FROM tbl WHERE nha_id = ', top_id, ' INTO #ids_tmp' SEPARATOR '');
PREPARE stmt FROM #str;
EXECUTE stmt;
WHILE #ids_tmp != "" DO
SET ids_all = GROUP_CONCAT(ids_all, #ids_tmp SEPARATOR ', ');
SET #str = GROUP_CONCAT('SELECT GROUP_CONCAT(id SEPARATOR \', \') ',
'FROM tbl WHERE nha_id IN (', #ids_tmp, ') INTO #ids_tmp' SEPARATOR '');
PREPARE stmt FROM #str;
EXECUTE stmt;
END WHILE;
SELECT ids_all AS ids;
END $$
DELIMITER ;
The problem is this routine is generating the following error when I try to call it (and sometimes it returns this error when I try to create the Stored Procedure):
ERROR 1111 (HY000): Invalid use of group function
When I manually create the same kinds of queries this code would build and run them at the command-line, they work perfectly fine -- no errors of any kind, and I get the results I expect. I've seen posts (both here on Stack Exchange and elsewhere) which say that MySQL doesn't support nested aggregate functions, but the concatenation here is just being done to strings. So I thought that maybe somehow it was seeing the GROUP_CONCAT in the string and burping because of that, so I tried putting "XXXX" in place of "GROUP_CONCAT" in the string and then using the REPLACE function to switch it back, but that made no difference. I also tried it with WHERE and HAVING for the criteria clause, but neither one worked. I've also done an extensive web search and was unable to find anything that was in any way helpful.
I don't know what else to try, mainly because I can't see what's wrong with the syntax here. Any help would be appreciated.
Update 1:
I have since tried a modified version of the script where the GROUP_CONCAT merges data from a subquery like this:
SET #qrystr = GROUP_CONCAT('SELECT GROUP_CONCAT(c SEPARATOR ", ") ',
'FROM (SELECT id AS c FROM tbl WHERE nha_id IN (', #ids_tmp,
') AS d INTO #ids_tmp' SEPARATOR '');
but that made no difference either.
You can't use GROUP_CONCAT() as a scalar function; it must be used in the context of a set of rows. Similarly, you can't use any other aggregate function without a table reference:
SET #x = MAX(<expr>); -- makes no sense
Ideally you should upgrade to MySQL 8.0 if you haven't already, and use a recursive CTE query instead:
WITH RECURSIVE hierarchy AS (
SELECT top_id AS id
UNION
SELECT tbl.id FROM tbl JOIN hierarchy ON tbl.nha_id = hierarchy.id
)
SELECT GROUP_CONCAT(id SEPARATOR ', ') AS ids_all FROM hierarchy;
That would eliminate the need for using loops or prepare/execute or temp variables.
Thanks to Bill Karwin's answer regarding the need to use SELECT with GROUP_CONCAT, I was able to see how my code needed to be changed. Rather than using a SET statement to assign the values to the variables, I need to use a SELECT ... INTO ... construct, as shown here:
DELIMITER $$
CREATE PROCEDURE ASSEMBLY_LIST_TEST (top_id INT)
BEGIN
DECLARE ids_all TEXT DEFAULT '';
SET SESSION group_concat_max_len = 1000000;
SET ids_all = top_id;
# Find the 1st-level children of 'top_id' to start building the list
SELECT GROUP_CONCAT('SELECT GROUP_CONCAT(id SEPARATOR ", ") FROM tbl ',
'WHERE nha_id = ', top_id, ' INTO #ids_tmp' SEPARATOR '') INTO #qrystr;
PREPARE stmt FROM #qrystr;
EXECUTE stmt;
# Recursively find the children of each level of children of the previous loop & add to the list
WHILE #ids_tmp != '' DO
SELECT GROUP_CONCAT(ids_all, ', ', #ids_tmp SEPARATOR '') INTO ids_all;
SELECT GROUP_CONCAT('SELECT GROUP_CONCAT(id SEPARATOR ", ") FROM tbl ',
'WHERE nha_id IN (', #ids_tmp, ') INTO #ids_tmp' SEPARATOR '') INTO #qrystr;
PREPARE stmt FROM #qrystr;
EXECUTE stmt;
END WHILE;
SELECT ids_all AS ids;
END $$
DELIMITER ;
This now produces exactly the result I was looking for. Of course, the recursive query approach is a much better solution for what I want this to do, but maybe my solution will help someone else.

Using tablenames as argument in execute prepared statement

Working in the query-box of phpMyAdmin I want to write an outfile 'protokoll' for each table in a MySQL 5.5 database. As I have many databases that contain the same tables and are different by name only, I want the filename of the outfile to look like
/tmp/dbname_protokoll_tablename_.csv
This works:
SELECT DATABASE() into #client;
SET #dir = '/tmp/';
SET #table = 'Adressen';
SET #stmt = CONCAT( 'SELECT * from ', #table, ' WHERE MarkDel=1 into outfile ''', #dir, #client , '_Protokoll_', #table , '.csv'' CHARACTER SET utf8 FIELDS TERMINATED BY '','' OPTIONALLY ENCLOSED BY ''"'' LINES TERMINATED BY ''\r\n'' ');
PREPARE DoExport from #stmt;
EXECUTE DoExport;
DEALLOCATE PREPARE DoExport;
From what I read about prepare, I should be able to use a '?' inside the statement, like
SET #stmt = CONCAT( 'SELECT * from ? WHERE MarkDel=1 into outfile ...
and then execute this with a list of arguments like
EXECUTE DoExport USING 'Adressen', 'Familien', 'Kinder';
but I can't get this to work, all I receive is an unspecific syntax error. How do I have to rewrite this?

How to handle where clause within mysql procedure?

Here is my procedure.
DELIMITER //
drop procedure if exists GetID;
CREATE PROCEDURE GetID(IN tb VARCHAR(255), in name2 varchar(255))
BEGIN
set #sel = concat( 'select id FROM ', tb, ' WHERE ename = ', name2);
prepare stmt from #sel;
execute stmt;
deallocate prepare stmt;
END //
DELIMITER ;
When I tried to execute the stored procedure by using GetID('city', 'ny'). I got an error
unknown column 'ny' in where clause ...
Here 'city' is the table name. What is wrong?
Assuming that name2 is a string parameter which to be compared with ename column of the passed table
Put quotes around name2 in the SQL:
set #sel = concat('select id FROM ', tb, ' WHERE ename = ''', name2,'''');
It's usually recommended not to use string concatenation to build SQL queries. Since you are hardcoding the column name in the query, it makes little sense to provide the table name "dynamically". But, if you must, use QUOTE to properly escape and quote the passed string.
set #sel = concat('select id FROM ', tb, ' WHERE ename = ', quote(name2));
Never concatenate strings directly into queries. It's bad enough that you're passing a table name in, unsanitized. That needs to be fixed, too, but one correct solution to your immediate issue is this:
set #sel = concat( 'select id FROM ', tb, ' WHERE ename = ', QUOTE(name2));
The QUOTE() function correctly and safely quotes and escapes the argument, and also handles null values correctly... and prevents a SQL injection vulnerability here.
See https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_quote.

Is it possible to dynamically create the name of a table in a stored procedure with MySQL?

Take a look at this code. It should show you what I am trying to do:
SELECT type from barcodes where barcode = barcodeApp INTO #barcodeType;
IF (#barcodeType = 'videogame') THEN
SET #barcodeType = 'game';
END IF;
DELETE FROM #barcodeType + itemdetails_custom
WHERE barcode = barcodeApp
AND username = usernameApp;
As you can see, on the DELETE FROM part, I would like to dynamically put together the table name from a result of a previous query. Is this possible?
Also, if you see issues with the above queries, please let me know. I'm by no means a MySQL expert obviously.
You need to use Prepared Statement to execute dynamically prepared queries.
Try following code:
set #del_query = concat( 'DELETE FROM ', #finalType )
set #del_query = concat( '\'', itemdetails_custom, '\'' );
set #del_query = concat( #del_query, ' WHERE barcode = \'', barcodeApp, '\'' );
set #del_query = concat( #del_query, ' AND username = \'', usernameApp, '\'' );
prepare stmt from #del_query;
execute stmt;
drop prepare stmt; -- deallocate prepare stmt;
Note: I assumed that barcodeApp and usernameApp are variables. Otherwise remove single quotes around them in the query above.