Changing Multiple DB Fields to Lower Case - mysql

With phpMyAdmin, I can use the following SQL to change all values in the table.field mytable.Site to lower case...
UPDATE my_table SET Site=LOWER(Site)
I have a zillion tables that have this same field, and I'd like to change all of them to lower case. Is there a SQL command that will do that - change EVERY field named Site in every table to lower case (preferably without having to list every table that has that field)?

Not EXACTLY what you want,but pretty close.Tested on my machine.
First create a procedure
delimiter //
CREATE PROCEDURE test(IN tbl CHAR(64))
BEGIN
SET #s = CONCAT('UPDATE ',tbl,' SET Site=LOWER(Site)' );
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
//
delimiter ;
And for finding tables with a certain column name:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN ('Site')
AND TABLE_SCHEMA='YourDB';
For calling the procedure
CALL test('tableName')

Related

TRUNCATE all tables matching name pattern

This is the sql i'm using based from this answer:
SET #pattern = '%_movielist';
SELECT concat('TRUNCATE TABLE ', GROUP_CONCAT(concat(TABLE_NAME)), ';')
INTO #truncatelike FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE #pattern;
SELECT #truncatelike;
PREPARE stmt FROM #truncatelike;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
but I get this error Access denied for user 'root'#'%' to database 'information_schema'.
What am I doing wrong? It seems to work for other users
You trying to execute this statement on "information_schema" database. Read more about this database [https://dev.mysql.com/doc/refman/5.7/en/information-schema.html]
You should not be running statements on the information_schema database (unless you REALLY know what you're doing). The database serves as a "meta" repository that dictates how the server operates. Chances are that you have no need to touch it and you'll likely brick your server if you do.
This is already answered here. [#1044 - Access denied for user 'root'#'localhost' to database 'information_schema'
Restriction to above: This query will work only if the no of table returned by the statement is 1 for more than 1 tables, you will require to use it in iteration.
To make this work for all the table matching the pattern we would require to use stored procedure.
Please change the Procedure name
CREATE PROCEDURE `new_procedure`()
BEGIN
-- Pattern to Match
SET #pattern = '%_movielist';
-- Temporary Table to Store the Result of The Select Statement
CREATE TEMPORARY TABLE IF NOT EXISTS Table_ToBeTruncated
(
Id int NOT NULL AUTO_INCREMENT,TableName varchar(100),
PRIMARY KEY (id)
);
-- Insert all the TableName to be Truncated
insert Table_ToBeTruncated(TableName)
SELECT distinct concat('TRUNCATE TABLE `', TABLE_NAME, '`;')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE #pattern and TABLE_SCHEMA = 'movielist';
-- Declare a variable to count the no of records to be truncated.
SET #count=(Select count(*)from Table_ToBeTruncated);
-- Iterate the list
WHILE #count> 0 DO
-- Pick One table from the Temporary Table List;
SELECT TableName into #truncatelike from Table_ToBeTruncated where ID= #count;
-- Prepare the statement
PREPARE stmt FROM #truncatelike;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Decrease the counter.
set #count = #count- 1;
END WHILE;
drop TEMPORARY TABLE IF EXISTS Table_ToBeTruncated ;
END

How do I select every row from a table based on a string containing the name of the table?

In MySQL, I have a number of procedures which are more or less identical - they all perform the same (or very similar) operations, but they perform it on different tables.
I'd like to reduce these to one procedure, parameterized by table name, if possible. For example, suppose I wanted to execute a generic select:
SELECT * FROM TableFor("TableName")
Is this (or anything similar) possible in MySQL? Is it possible in any SQL dialect?
Per Tomva's Answer
A full example:
DROP PROCEDURE IF EXISTS example;
CREATE PROCEDURE example(IN tablename VARCHAR(1000)) BEGIN
SET #statement = CONCAT('SELECT * FROM ', #tablename);
PREPARE statement FROM #statement;
EXECUTE statement;
DEALLOCATE PREPARE statement;
END;
CALL example('tablename');
You can do this with a prepared statement.
It will be something along the lines of
SET #stat = CONCAT('SELECT * FROM ', #tab');
PREPARE stat1 FROM #stat;
EXECUTE stat1;
DEALLOCATE PREPARE stat1;
Dynamic SQL does not work in a function, so make a Stored Procedure from this, and you will be able to provide the table parameter.
I am going to assume you know what a stored procedure is (I hope you do otherwise my answer will be useless)
First create a table object in your procedure
declare #tablenames table(name varchar)
insert into #MonthsSale (name) values ('firsttable')
insert into #MonthsSale (name) values ('secondtable')
...
You can add this little line to suppress the rows affected messages:
SET NOCOUNT ON
Then create a cursor for this table and a variable to save your table name
DECLARE #TABLENAME VARCHAR
DECLARE tables_cursor CURSOR FOR SELECT name FROM #tablenames
Then loop through cursor and execute your code for each table name
OPEN Tables_cursor
FETCH NEXT FROM Tables_cursor INTO #Tablename
WHILE ##FETCH_STATUS = 0
BEGIN
YOUR CODE USING THE #Tablename
END
CLOSE Tables_cursor
DEALLOCATE Tables_cursor

mysql dynamic query in stored procedure

i am creating a dynamic query in stored procedure. my stored procedure is as follows:
CREATE PROCEDURE `test1`(IN tab_name VARCHAR(40),IN w_team VARCHAR(40))
BEGIN
SET #t1 =CONCAT("SELECT * FROM ",tab_name," where team=",w_team);
PREPARE stmt3 FROM #t1;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
END
when i try to run it with the following call:
call test1 ('Test','SPA');
i get the following error message:
Error Code: 1054. Unknown column 'SPA' in 'where clause'
i tested without where condition and it works fine, but with the where condition its not working, i tried using # with the variable name but it still does not work.
Thanks for your help.
Error Code: 1054. Unknown column 'SPA' in 'where clause'
This happens when you do not enclose input string within quotes, and SQL engine tries to identify it as a column in the table being queried. But it fails as it can't find it.
But what happens when it finds such column?
It fetches results when it finds some matches on the column values.
Obviously this is not what one was expecting.
How to overcome this? Use Prepared Statements with dynamic input values.
You can use placeholders like ? in stored procedures too on dynamic input values to use with Prepared Statements. The engine will handle escape characters and other string values when assigned to or compared within SQL expressions.
You just need to re-assign procedure inputs to one or more session variables, as required.
Example on your procedure:
CREATE PROCEDURE `test1`( IN tab_name VARCHAR(40), IN w_team VARCHAR(40) )
BEGIN
SET #t1 = CONCAT( 'SELECT * FROM ', tab_name, ' where team = ?' ); -- <-- placeholder
SET #w_team := w_team;
PREPARE stmt3 FROM #t1;
EXECUTE stmt3 USING #w_team; -- <-- input for placeholder
DEALLOCATE PREPARE stmt3;
END;
You missed to enclose the parameter w_team in WHERE clause.
Try like this:
SET #t1 =CONCAT("SELECT * FROM ",tab_name," where team='",w_team,"'");
Explanation:
Query from your code would be like:
SELECT * FROM Test where team=SPA
It will try find a column SPA which is not available, hence the error.
And we changed it to:
SELECT * FROM Test where team='SPA'
Try this..
CREATE PROCEDURE `test1`(IN tab_name VARCHAR(40),IN w_team VARCHAR(40))
BEGIN
SET #t1 =CONCAT("SELECT * FROM ",tab_name," where team='",w_team,"'");
PREPARE stmt3 FROM #t1;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
END
You are missing quotes around w_team variable..
you should print the statement that dynamically build so you can just copy printed statement and try so you can easily find this kind of problem.
select #t1 will print the statment that build dynamically..
you can add dynamic fields and condition by using CONCAT() MySQL function. I checked this is working fine.
DELIMITER $$
/*define procedure name*/
CREATE PROCEDURE getSearchData()
BEGIN
DECLARE conditions varchar(1000);
DECLARE selectField varchar(1000);
DECLARE SQL_QUERY varchar(1000);
/*define default select and condition*/
SET #selectField = 'status,id';
set #conditions = ' where return_flight=0';
SET #SQL_QUERY = CONCAT('SELECT ',#selectField, ' FROM flights ',#conditions);
/* you can add more select fields and conditions according to your requirement */
PREPARE stmt1 FROM #SQL_QUERY ;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END$$
DELIMITER ;

Iterate MySQL schemas

Problem description
I have a single-tenant MySQL database setup. That is, I have one identical schema for each client.
Now I need to run a specific query for each client. That would be easy in a multi-tenant setting (where all clients share a single schema). With my setup however, I need to iterate the schemas. More generally, I want to access a schema whose name is given by a variable. How can that be done?
What I've tried
If I try USE varSchemaName (where varSchemaName is a varchar
variable), I get the error message ERROR 1314: USE is not allowed
in stored procedures.
If I try SELECT * FROM varSchemaName.MyTable I get
Error Code: 1146. Table 'varSchemaName.MyTable' doesn't exist. Apparently MySQL considers varSchemaName to be a literal, not a
variable.
Building on the answer from fancyPants, you can call that procedure within a loop from another procedure which queries information_schema.tables to identify the databases containing MyTable and then call fancyPants' procedure with the db names as a parameter. This method is easy if the databases have a consistent naming scheme or contain identically named objects, which sounds like the case here. The structure would be something like:
DELIMITER //
DROP PROCEDURE IF EXISTS mydriver //
CREATE PROCEDURE mydriver()
BEGIN
DECLARE varSchemaName VARCHAR(64);
DECLARE done BOOLEAN;
DECLARE cur CURSOR FOR
SELECT table_schema
FROM information_schema.tables
WHERE table_name = 'MyTable';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
FETCH cur INTO varSchemaName;
IF done THEN
LEAVE read_loop;
CLOSE cur;
END IF;
CALL fancypants_proc(varSchemaName);
END LOOP;
END //
DROP PROCEDURE IF EXISTS fancypants_proc //
CREATE PROCEDURE fancypants_proc(IN varSchemaName VARCHAR(64))
BEGIN
SET #sql = CONCAT('SELECT * FROM ', varSchemaName, '.MyTable');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
CALL mydriver();
You have to build the statement first.
SET #sql = CONCAT('SELECT * FROM ', varSchemaName, '.MyTable');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
You can read more about prepared statements here.
You might be tempted to use variables for tablenames, but that doesn't work. Those parameters are for values in where clauses and so on. The above way is the way to go.

use a variable for table name in mysql sproc

I'm trying to pass a table name into my mysql stored procedure to use this sproc to select off of different tables but it's not working...
this is what I"m trying:
CREATE PROCEDURE `usp_SelectFromTables`(
IN TableName varchar(100)
)
BEGIN
SELECT * FROM #TableName;
END
I've also tried it w/o the # sign and that just tells me that TableName doesn't exist...which I know :)
SET #cname:='jello';
SET #vname:='dwb';
SET #sql_text = concat('select concept_id,concept_name,',#vname,' from enc2.concept a JOIN enc2.ratings b USING(concept_id) where concept_name like (''%',#cname,'%'') and 3 is not null order by 3 asc');
PREPARE stmt FROM #sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
An extra bit that caused me problems.
I wanted to set the table name and field dynamically in a query as #kyle asked, but I also wanted to store the result of that query into a variable #a within the query.
Instead of putting the variable #a into the concat literally, you need to include it as part of the string text.
delimiter //
CREATE PROCEDURE removeProcessed(table_name VARCHAR(255), keyField VARCHAR(255), maxId INT, num_rows INT)
BEGIN
SET #table_name = table_name;
SET #keyField = keyField;
SET #maxId = maxId;
SET #num_rows = num_rows;
SET #sql_text1 = concat('SELECT MIN(',#keyField,') INTO #a FROM ',#table_name);
PREPARE stmt1 FROM #sql_text1;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
loop_label: LOOP
SET #sql_text2 = concat('SELECT ',#keyField,' INTO #z FROM ',#table_name,' WHERE ',#keyField,' >= ',#a,' ORDER BY ',#keyField,' LIMIT ',#num_rows,',1');
PREPARE stmt2 FROM #sql_text2;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2;
...Additional looping code...
END LOOP;
END
//
delimiter ;
So in #sql_text1 assign the result of the query to #a within the string using:
') INTO #a FROM '
Then in #sql_text2 use #a as an actual variable:
,' WHERE ',#keyField,' >= ',#a,' ORDER BY '
It depends on the DBMS, but the notation usually requires Dynamic SQL, and runs into the problem that the return values from the function depend on the inputs when it is executed. This gives the system conniptions. As a general rule (and therefore probably subject to exceptions), DBMS do not allow you to use placeholders (parameters) for structural elements of a query such as table names or column names; they only allow you to specify values such as column values.
Some DBMS do have stored procedure support that will allow you to build up an SQL string and then work with that, using 'prepare' or 'execute immediate' or similar operations. Note, however, that you are suddenly vulnerable to SQL injection attacks - someone who can execute your procedure is then able to control, in part, what SQL gets executed.