Using tablenames as argument in execute prepared statement - mysql

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?

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 char displaying just the first character

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

MySQL: Dynamically export CSV file with headers

Is there anyway to export data in MySQL table with column headers?
I find a way to do this by hard-coding the headers into query but if there are about 60 or even 100 columns in a table then it is impossible.
I tried the query below but I can't get the result as the first part of the query return a concatenated string of all headers in the table. It doesn't give me a desired result:
(select concat(group_concat(COLUMN_NAME separator ','), "\n")
from information_schema.COLUMNS
where table_name = '<table name>'
and table_schema = '<DB name>'
order by ORDINAL_POSITION)
union all
(select * from <table name> into outfile "E:\\test.csv" fields terminated by "," lines terminated by "\n");
There are few ways to fetch the field names of table in mysql, but below method works the best for outfile.
The filename of the csv file is dynamically created based on the datestamp, and for this prepared statement is used.
-- ensure mysql user has write permission on below location
SET #effectiveFileName = CONCAT('/home/myhome/temp-dev/', 'mytable','_', DATE_FORMAT(NOW(), '%Y-%m-%d'), '.csv');
-- group concat default is 1024, to avoid field names getting truncated we increase this value
SET SESSION group_concat_max_len = 10000;
SET #queryStr = (
SELECT
CONCAT('SELECT * INTO OUTFILE \'',
#effectiveFileName,
'\' FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'"\' LINES TERMINATED BY \'\n\' FROM (SELECT ',
GROUP_CONCAT(CONCAT('\'', COLUMN_NAME, '\'')),
'UNION ALL SELECT * FROM myschema.mytable WHERE myschema.mytable.myfield <=\'',
CURDATE(),
'\') as tmp')
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = 'mytable' AND
TABLE_SCHEMA = 'myschema'
ORDER BY ORDINAL_POSITION
);
PREPARE stmt FROM #queryStr;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Below is simple version of above query with static file name.
-- group concat default is 1024, to avoid field names getting truncated we increase this value
SET SESSION group_concat_max_len = 10000;
SELECT
CONCAT('SELECT * INTO OUTFILE \'/home/myuser/myfile.csv\' FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'"\' ESCAPED BY \'\' LINES TERMINATED BY \'\n\' FROM (SELECT ',
GROUP_CONCAT(CONCAT('\'', COLUMN_NAME, '\'')),
' UNION select * from YOUR_TABLE) as tmp')
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = 'YOUR_TABLE'
AND TABLE_SCHEMA = 'YOUR_SCHEMA'
ORDER BY ORDINAL_POSITION;
(SELECT 'Order Number','Order Date','Status')
UNION
(SELECT orderNumber,orderDate, status
FROM orders
INTO OUTFILE 'C:/tmp/orders.csv'
FIELDS ENCLOSED BY '"' TERMINATED BY ';' ESCAPED BY '"'
LINES TERMINATED BY '\r\n');

mysql stored procedure outfile

I am trying to write SP query results to file nad get a consistent error code: 1086 File already exists. This is despite the fact that the file name has to be unique because it's containing a random generate number.
Here is part of my code:
SET fullOutputPath = CONCAT(user,'_',FLOOR(1000+RAND()*9999),'.txt');
SELECT fullOutputPath;
-- write the resultset to the file
SELECT node_concat
INTO OUTFILE ",fullOutputPath,"
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY ''
LINES TERMINATED BY '\n'
FROM sn_neighbour_tmp;
Any ideas ?
You need to use 13.5 SQL Syntax for Prepared Statements.
Example:
...
SET `fullOutputPath` := CONCAT(USER, '_', FLOOR(1000 + RAND() * 9999), '.txt');
SET #`qry` := CONCAT('SELECT `node_concat`
INTO OUTFILE ', `fullOutputPath`, '
FIELDS TERMINATED BY \',\'
OPTIONALLY ENCLOSED BY \'\'
LINES TERMINATED BY \'\n\'
FROM `sn_neighbour_tmp`');
PREPARE `stmt` FROM #`qry`;
SET #`qry` := NULL;
EXECUTE `stmt`;
DEALLOCATE PREPARE `stmt`;
...

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.