I'm trying to rename a list of tables using a constant prefix defined as a #var:
SET #p='newprefix_';
RENAME TABLE `oldprefix_tablename1` TO CONCAT(#p, 'tablename1');
RENAME TABLE `oldprefix_tablename2` TO CONCAT(#p, 'tablename2');
This syntax is wrong, but I see that:
SELECT CONCAT(#p, 'tablename'); //outputs newprefix_tablename
What's the correct way/syntax to use here?
You can't do it directly the way you are trying. As the manual says (http://dev.mysql.com/doc/refman/5.1/en/user-variables.html)
User variables are intended to provide data values. They cannot be
used directly in an SQL statement as an identifier or as part of an
identifier, such as in contexts where a table or database name is
expected, or as a reserved word such as SELECT.
You have to use prepared statements:
SET #p = 'newprefix_';
SET #s = CONCAT('RENAME TABLE `oldprefix_tablename1` to ', #p, 'tablename1');
PREPARE stmt FROM #s;
EXECUTE stmt;
Related
set #tmpGuid = REPLACE( uuid(),'-',''); set #fieldName = concat('deneme' , '_' , #tmpGuid); ALTER TABLE table_name RENAME COLUMN deneme to #fieldName;
https://i.stack.imgur.com/ciQ44.png
how can use my variable on mysql commands
Variables are meant to store data, not code. In SQL, table and column names count as the latter. From User-Defined Variables:
User variables are intended to provide data values. They cannot be used directly in an SQL statement as an identifier or as part of an identifier, such as in contexts where a table or database name is expected, or as a reserved word such as SELECT.
Many DBMS don't allow DDL statements to be parameterised. I.e. alter, create statements and such.
However this doesn't mean it's impossible. What you'd need to do is convert your statement to dynamic SQL, which you can manipulate in every way possible (including inserting parameters into the string).
Then simply executing it.
In your example:
SET #tmpGuid = REPLACE( uuid(),'-','');
SET #fieldName = concat('deneme' , '_' , #tmpGuid);
SET #sql = CONCAT('ALTER TABLE table_name RENAME COLUMN deneme to ', #fieldName);
PREPARE dynamic_SQL FROM #sql;
EXECUTE dynamic_SQL;
DEALLOCATE PREPARE dynamic_SQL;
Ofcourse using dynamic SQL has it's own troubles, and opens up potential risks. But it's the only way to do something like this.
See it in action: Here
I am trying add one column in my Mysql database that sums all the columns starting by 'tokenvalid' which can take the value of 1 or 0.
And let's say I have 50 columns like that in my database (i.e. tokenvalid1, tokenvalid2 ...., tokenvalide50) with other columns between.
Please find below the code I would like to implement. I know that is not correct at all but it is just to give you an idea of what I am trying to do.
Thank you for your help!
'SELECT *, sum(column_name LIKE "tokenvalid"%) as total FROM points WHERE 1'
This post should help you. The post describes how to get the columns and then query for results.
MySQL Like statement in SELECT column_name
Something like this should help you.
SET #colname = (SELECT GROUP_CONCAT(`column_name`) from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='points' AND `column_name` LIKE 'tokenvalid%');
SET #table = 'points';
SET #query = CONCAT('SELECT SUM(',#colname,') FROM ', #table);
PREPARE stmt FROM #query;
EXECUTE stmt;
Similar to this answer by RocketDonkey
If the string is in your external application (like PHP), sure, just construct the MySQL statement.
If the string is inside a MySQL table, you can't. MySQL has no eval() or such function. The following is impossible:
Suppose you have a table 'queries' with a field "columnname" that refers to one of the column names in the table "mytable". There might be additional columns in 'queries' that allow you to select the columnname you want...
INSERT INTO queries (columname) VALUES ("name")
SELECT (select columnname from queries) from mytable
You can however work with PREPARED STATEMENTS. Be aware this is very hacky.
SELECT columnname from queries into #colname;
SET #table = 'mytable';
SET #s = CONCAT('SELECT ',#colname,' FROM ', #table);
PREPARE stmt FROM #s;
EXECUTE stmt;
First I create my table with one text column in 5.6.34 - MySQL Community Server (GPL) like so :
CREATE TABLE `$_query_test`.`t1` ( c1 TEXT NOT NULL ) ENGINE = InnoDB;
Then I execute:
SET #var = 321; INSERT INTO `t1` (c1) VALUES (#var);
I get one entry with a value of 321 as expected, but when i execute:
SET #var = '_string_';
ALTER TABLE `t1` ADD #var TEXT;
I get an error
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near '#var TEXT' at line 1
What is the proper syntax to do something like this? I have searched far and wide and so far got nothing on this.
The answer is that you cannot substitute an sql variable in place of an identifier (e.g. field name, table name, etc). Period.
What you can do is to create the full sql statement as a string either on application level or in mysql with the identifier already substituted and you execute the full statement.
In mysql you can do this via prepared statements:
PREPARE stmt1 FROM CONCAT('ALTER TABLE `t1` ADD ', #var, ' TEXT');
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
You can use variables for values but not field names. You will need to do that with whatever server language you are using before composing the alter table.
I've found another thread on this question, but I wasn't able to use its solutions, so I thought I'd ask with more clarity and detail.
I have a large MySQL database representing a vBulletin forum. For several years, this forum has had an error generated on each view, each time creating a new table named aagregate_temp_1251634200, aagregate_temp_1251734400, etc etc. There are about 20,000 of these tables in the database, and I wish to delete them all.
I want to issue a command that says the equivalent of DROP TABLE WHERE TABLE_NAME LIKE 'aggregate_temp%';.
Unfortunately this command doesn't work, and the Google results for this problem are full of elaborate stored procedures beyond my understanding and all seemingly tailored to the more complex problems of different posters.
Is it possible to write a simple statement that drops multiple tables based on a name like match?
There's no single statement to do that.
The simplest approach is to generate a set of statements, and execute them individually.
We can write a simple query that will generate the statements for us:
SELECT CONCAT('DROP TABLE `',t.table_schema,'`.`',t.table_name,'`;') AS stmt
FROM information_schema.tables t
WHERE t.table_schema = 'mydatabase'
AND t.table_name LIKE 'aggregate\_temp%' ESCAPE '\\'
ORDER BY t.table_name
The SELECT statement returns a rowset, but each row conveniently contains the exact SQL statement we need to execute to drop a table. (Note that information_schema is a builtin database that contains metadata. We'd need to replace mydatabase with the name of the database we want to drop tables from.
We can save the resultset from this query as a plain text file, remove any heading line, and voila, we've got a script we can execute in our SQL client.
There's no need for an elaborate stored procedure.
A little googling found this:
SELECT 'DROP TABLE "' + TABLE_NAME + '"'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'prefix%'
This should generate a script.
Source: Drop all tables whose names begin with a certain string
From memory you have to use prepared statements, for example: plenty of samples on stack exchange
I would recommend this example:
SQL: deleting tables with prefix
The SQL from above, this one includes the specific databasename - it builds it for you
SELECT CONCAT( 'DROP TABLE ', GROUP_CONCAT(table_name) , ';' )
AS statement FROM information_schema.tables
WHERE table_schema = 'database_name' AND table_name LIKE 'myprefix_%';
Here is a different way to do it:
MySQL bulk drop table where table like?
This will delete all tables with prefix "mg_"
No need to copy and paste rowsets and in phpadmin copying and pasting is problematic as it will cut off long table names and replace them with '...' ruining set of sql commands.
Also note that '_' is a special character so thats why 'mg_' should be encoded as 'mg\_'
(and FOREIGN_KEY_CHECKS needs to be disabled in order to avoid error messages)
SET FOREIGN_KEY_CHECKS = 0;
SET GROUP_CONCAT_MAX_LEN=32768;
SET #tables = NULL;
SELECT GROUP_CONCAT('`', table_name, '`') INTO #tables
FROM information_schema.tables
WHERE table_schema = (SELECT DATABASE()) and table_name like 'mg\_%';
SELECT IFNULL(#tables,'dummy') INTO #tables;
SET #tables = CONCAT('DROP TABLE IF EXISTS ', #tables);
PREPARE stmt FROM #tables;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET FOREIGN_KEY_CHECKS = 1;
I want to create a database where there is a list of table names stored in a table. Now with the help of this list I can access the other tables.
Ex :-
Table name :- table_list (2 column i.e. table_name,table_id)
table_list attributes
authentication 1
basic_info 2
contact 3
I can directly access these tables using select statement but I want to access them using the table_list table preferably using select statement.
I tried
select * from (select table_name as x from table_list where id=2) as y
But could not get the proper output.
It is called Prepared Statements and their only use is when you want to implement your mentioned need in one request. Otherwise you can easily retrieve table names in a programming language and create your next statement using the data in hand. Here's how Prepared Statements work:
SELECT table_name INTO #tbl FROM my_tables WHERE id = 1 LIMIT 1;
SET #sql := CONCAT('SELECT * FROM ', #tbl);
PREPARE stmt1 FROM #sql;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
TRY THIS
select * from (SELECT TABLE_NAME FROM TABLE_LIST WHERE ID=2)as y
The table name (an "identifier") must be a static part of the SQL text issed to the database; the identifier can't be supplied "on the fly", either as a parameter or as a result from another SQL query.
To do what you want to do, you will need a two step approach. You can use one (or more) SQL statements to obtain the identifiers you need (table name, column names, etc.), and then use that to dynamically create a second SQL statement, as a string.
The identifiers (table names, column anmes) can not be provided as parameters or "bind variables", they must be a static part of the SQL text.
For example, to generate the statement:
SELECT CONCAT('SELECT * FROM `',table_name,'` ORDER BY 1') AS stmt
FROM table_list
WHERE id = 2
(The coding details are dependent on what language you are using.)
Since you are sure that the table name you want to access is x, just check whether such a table exists using a query and use x for future purpose.