Iam working on MYSQL and need a stored procedure that will traverse through table A which has 100 columns and 50,000+ rows and for all Null values found in the table the SP will update it with blank values.
eg
UPDATE table A SET column1=' ' where column1 IS NULL;
column1 is mixture of null and filled and blank rows,but i want to update only null rows.
I do not want to hardcode the column names..want to fetch the columns one by one in the stored procedure itself.is this possible?
You could dynamically fetch the column names from your tables.
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'my_database' AND TABLE_NAME = 'my_table';
And combine this using inner queries.
Use the mysql ifnull function.You will need the below for all hundred columns. This can be used on string/char as well as integer fields.
update table
set
field1=ifnull(field1, " "),
field2=ifnull(field2, " "),
field3=ifnull(field3, 0),
field4=ifnull(field4, "")....
If you don't want to hardcode the column names, you can build the above query as per the other answer:
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'my_database' AND TABLE_NAME = 'my_table';
For each of the above rows, build a concatenated update statement.
DEClARE usercursor CURSOR FOR
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'my_database' AND TABLE_NAME = 'my_table';
declare updatesql varchar(3000);
set updatesql = "update TABLE set ";
OPEN usercursor
get_users:LOOP
FETCH usercursor into v_username;
set updatesql = concat(v_username,"=ifnull(",updatesql)
set updatesql = concat(v_username,",' '),",updatesql)
END LOOP get_users
What would be the proper syntax used to run an update query on a table to remove all spaces from the values in a column?
I have a user table that had user names with spaces imported into it & I need to remove the spaces. i.e. "john smith sr." needs to be "johnsmithsr."
there are about 500+ occurrences.
You could try something like this:
UPDATE `table` SET `column` = REPLACE( `column` , ' ' , '' )
UPDATE <table>
SET name = REPLACE(name, ' ', '') ;
500+ occurences is not that much so this should execute in no time
Try this
update table_name set column_name = replace(column_name, ' ', '');
The second argument will be replaced by the third argument.
I think this is what we are looking for
SELECT some_columns FROM table_name WHERE REPLACE(col_name, ' ', '') LIKE 'some string';
This is probably your answer:
SELECT replace(col_name , ' ','') FROM table_name;
Is the following query an acceptable way to convert the fields' data_types?
UPDATE INFORMATION_SCHEMA.COLUMNS
SET `COLUMNS`.`DATA_TYPE` = 'tinyint'
WHERE
`COLUMNS`.`TABLE_SCHEMA` = 'BAR'
AND `COLUMNS`.`TABLE_NAME` = 'FOO'
AND `COLUMNS`.`DATA_TYPE` = 'bit'
Should I be concerned about data integrity or will data stored as bit move to tinyint without issue?
You can't directly modify the metadata tables (they're actually views but the distinction's not important for this case) but you can use them to generate your alter table statements, something like this:
SELECT 'ALTER TABLE ' + TABLE_SCHEMA + '.' + TABLE_NAME + ' ALTER COLUMN ' + COLUMN_NAME + ' TINYINT' + CASE WHEN IS_NULLABLE = 'YES' THEN ' NULL;' ELSE ' NOT NULL;' END
FROM INFORMATION_SCHEMA.COLUMNS
WHERE `COLUMNS`.`TABLE_SCHEMA` = 'BAR'
AND `COLUMNS`.`TABLE_NAME` = 'FOO'
AND `COLUMNS`.`DATA_TYPE` = 'bit'
This won't do. Operations UPDATE, DELETE, INSERT are not allowed on the INFORMATION_SCHEMA database.
Here's why.
to get numeric values from an ENUM column, can be using
mysql> SELECT enum_col+0 FROM tbl_name;
reference here
But in my mysql5.5 console,this query return:
1.0000000000000000000000000000000
I want to get the a integer number 1
I know I can use:
SELECT CONVERT(enum_col,UNSIGNED) FROM tbl_name;
or
SELECT CAST(enum_col AS UNSIGNED) FROM tbl_name;
I want to know why enum_col+0 return a float,
and any other way to get numeric values from an ENUM column?
Have a look at this article - Type Conversion in Expression Evaluation; it describes how MySQL does conversion between different types; there are some rules, in your case you get result as a floating-point value.
...and try another variant:
SELECT TRIM(TRAILING ')' FROM TRIM(LEADING '(' FROM TRIM(LEADING 'enum' FROM column_type))) INTO #enum
FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = 'db_name' AND TABLE_NAME = 'tbl_name' AND COLUMN_NAME = 'enum_col';
SELECT FIND_IN_SET(CONCAT('''', enum_col, ''''), #enum) FROM tbl_name
or this one:
SELECT REPLACE(TRIM(TRAILING ')' FROM TRIM(LEADING '(' FROM TRIM(LEADING 'enum' FROM column_type))), '''', '') INTO #enum
FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = 'db_name' AND TABLE_NAME = 'tbl_name' AND COLUMN_NAME = 'enum_col';
SELECT FIND_IN_SET(enum_col, #enum) FROM tbl_name
How do you insert selected rows from table_source to table_target using SQL in MySQL where:
Both tables have the same schema
All columns should transfer except for the auto-increment id
Without explicitly writing all the column names, as that would be tedious
The trivial INSERT INTO table_target SELECT * FROM table_source fails on duplicate entries for primary key.
Either you list all of the fields you want in the insert...select, or you use something else externally to build the list for you.
SQL does not have something like SELECT * except somefield FROM, so you'll have to bite the bullet and write out the field names.
Column names have to be specified -
INSERT INTO table_target SELECT NULL, column_name1, column_name2, column_name3, ...
FROM table_source;
Just pass NULL as a value for the auto-increment id field.
Of course, primary key must be unique. It depends on what you want to achieve, but you could exclude rows with a primary key that already exists.
INSERT INTO table_target SELECT * FROM table_source
WHERE table_source.id NOT IN (SELECT id FROM table_target)
UPDATE: since you also need the extra rows, you should resolve the conflict first, does table_source have relationships? If not you could change those keys:
UPDATE table_source SET id = id + 1000
WHERE id IN (SELECT id FROM table_target)
Where 1000, is a constant, big enough so they go after the end of your table.
Tedious but safe and correct.
Writing INSERT statements without providing a list of columns leads to code that's hard to debug and, more importantly, very fragile code that will break if the definition of the table is changed.
If you absolutely can't write the column names out yourself then it's relatively easy to build a tool into your code that will create the comma-separated list for you.
This is my final solution to mass update with 'replace insert' command.
SET ##session.group_concat_max_len = ##global.max_allowed_packet;
SET #schema_db = 'db';
SET #tabl = 'table';
SET #cols = (SELECT CONCAT('`',GROUP_CONCAT(COLUMN_NAME SEPARATOR '`, `'), '`') FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = #schema_db AND TABLE_NAME = #tabl GROUP BY TABLE_NAME);
SET #Querystr = CONCAT('REPLACE INTO ',#schema_db,'.',#tabl,' SELECT ', #cols,' FROM import.tbl_', #tabl);
PREPARE stmt FROM #Querystr;
EXECUTE stmt;
I think you could use syntax like:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
REF: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
Hope it helps
INSERT IGNORE just "bypass" the duplicate rows.
http://dev.mysql.com/doc/refman/5.5/en/insert.html
You can probably do it with prepared statements.
PREPARE table_target_insert FROM 'INSERT INTO table_target SELECT ? FROM table_source';
SET #cols:='';
SELECT #cols:=GROUP_CONCAT(IF(column_name = 'id','NULL',column_name) separator ",") FROM information_schema.columns WHERE table_name='table_source';
EXECUTE table_target_insert USING #cols;
It seems as if columns can not be given as a place holder in a MySQL Prepared Statement. I have compiled the following solution for testing:
SET #schema_db = 'DB';
SET #table = 'table';
SET #cols = (SELECT CONCAT(GROUP_CONCAT(COLUMN_NAME SEPARATOR ', '), "\n") FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = #schema_db AND TABLE_NAME = #table GROUP BY TABLE_NAME);
SET #Querystr = CONCAT('SELECT',' ', #cols,' ','FROM',' ',#schema_db,'.',#table,' ', 'Limit 5');
PREPARE stmt FROM #Querystr;
EXECUTE stmt;
You can use dynamic query:
DECLARE #Columns VARCHAR(MAX)=''
DECLARE #Query VARCHAR(MAX)=''
SELECT
#Columns = ISNULL(#Columns +',', '') + T.COLUMN_NAME
FROM
(
select name as COLUMN_NAME from sys.all_columns
where object_id = (select object_id from sys.tables where name = 'Source_Table')
and is_identity = 0
)T
set #Query = 'insert into Target_Table (' + SUBSTRING(#Columns,2 , 9999) + ') select ' + SUBSTRING(#Columns,2 , 9999) + ' from Source_Table';
PRINT #Query
EXEC(#Query)
The easiest way to do it is to use phpmyadmin to write the list of columns, then to change it as needed, in the example below I want to duplicate row with id=1078 and in this table I have id unique auto increment and alias unique.therefore I created my query as follow, with id & alias replaced by a desired value. and it worked like a charm.
INSERT INTO sy3_menuselect 1079, menutype, title, "alias", note, path, link, type, published, parent_id, level, component_id, checked_out, checked_out_time, browserNav, access, img, template_style_id, params, lft, rgt, home, language, client_id from sy3_menuwhere id=1078
Alternatively, to auto increment id, use the following Join statement:
INSERT INTO sy3_menuselect *
from (SELECT MAX(id+1 )from sy3_menu)a
join (select menutype, title, "alias", note, path, link, type, published, parent_id, level, component_id, checked_out, checked_out_time, browserNav, access, img, template_style_id, params, lft, rgt, home, language, client_idfrom sy3_menuwhere id=1079)b