ALTER TABLE ADD COLUMN and automatic COLUMNS list - mysql

I am looking to add a new column to table using the suggestions provided here and here
In essence, I would like the (fields_in_orig_table) to be populated automatically, and not having to enter them manually (have many columns and this changes from table to table):
CREATE TABLE games_new LIKE games_orig;
ALTER TABLE games_new ADD COLUMN location varchar(256);
INSERT INTO games_new (fields_in_orig_table) SELECT * FROM games_orig;
RENAME TABLE games_orig TO games_old, games_new TO games_orig;
DROP TABLE games_old;
My thought goes around this:
CREATE TABLE games_new LIKE games_orig;
ALTER TABLE games_new ADD COLUMN version varchar(256);
INSERT INTO games_new
(SELECT CONCAT(GROUP_CONCAT(column_name ORDER BY ordinal_position
SEPARATOR " , "), " ") AS columns
FROM information_schema.columns
WHERE table_schema = 'games' AND table_name = 'games_orig' )
SELECT * FROM games_orig;
RENAME TABLE games_orig TO games_old, games_new TO games_orig;
DROP TABLE games_old;
This gives me syntax error (near the Select concat....).
The original syntax to get comma delimited column listings is:
SELECT CONCAT("'", GROUP_CONCAT(column_name ORDER BY ordinal_position SEPARATOR "', '"), "'") AS columns
FROM information_schema.columns
WHERE table_schema = 'db_name' AND table_name = 'tbl_name'
In my query, I have removed the extra quotes, as I figure my query does not require quotes as part of the column listing.
What am I doing wrong here? Who could help, please?

INSERT INTO games_new
VALUES (SELECT CONCAT....

When inserting values in the table use INSERT INTO tablename VALUES (fields) instead of INSERT INTO tablename SET(fields).
CREATE TABLE games_new LIKE games_orig;
ALTER TABLE games_new ADD COLUMN version varchar(256);
INSERT INTO games_new
VALUES
(SELECT CONCAT(GROUP_CONCAT(column_name ORDER BY ordinal_position
SEPARATOR ' , '), ' ') AS columns
FROM information_schema.columns
WHERE table_schema = 'games' AND table_name = 'games_orig' )
SELECT * FROM games_orig;
RENAME TABLE games_orig TO games_old, games_new TO games_orig;
DROP TABLE games_old;

You haven't specified which column you want to insert into, because your nested query is returning only 1 value
INSERT INTO games_new (column_name_u_want_to_insert_value_into)
SELECT cast(concat(group_concat(column_name ORDER BY ordinal_position SEPARATOR " , "), " ") AS CHAR) AS columns
FROM information_schema.columns
WHERE table_name = 'games_orig';
also, if you are running all the statements together, add semicolon(;) for the insert query as well

Related

select column from multiple unknown tables

I have a lot of dynamically created nearly similar looking tables according to the scheme "prefix + number", eg "t1", "t2", "t343" etc. All those tables have a cross-table unique row named identifier that I like to select within one query:
SELECT
`identifier`
FROM
(
SELECT
`TABLE_NAME`
FROM
information_schema.TABLES
WHERE
`TABLE_NAME` LIKE 't%'
);
But this returns: ERROR 1248 (42000): Every derived table must have its own alias
EDIT: according to the comments I modified my query like this:
SELECT
A.identifier
FROM
(
SELECT
`TABLE_NAME` AS identifier
FROM
information_schema.TABLES
WHERE
`TABLE_NAME` LIKE 't%'
) A;
But this selects only the table names from the subquery but not the column identifier from these tables.
When you create the table dynamically, and you want to query all of them, you can create an SQL statement dynamically like:
select
group_concat(
concat(
'SELECT ',
'''',TABLE_SCHEMA,'.',TABLE_NAME,''',',
TABLE_SCHEMA,'.',TABLE_NAME,'.', COLUMN_NAME,
' FROM ',
TABLE_SCHEMA,'.',TABLE_NAME)
separator ' union all ')
from information_schema.`COLUMNS` c
where table_schema='test' -- the schema name where your tables are
and table_name regexp '^t[0-9]+$' -- table name starts with t and ends with number
and COLUMN_NAME = 'i' -- i choose `i` as the column to be selected
;
This will produce a SQL statement like:
select
'test.t1',
test.t1.i
from
test.t1
union all
select
'test.t2',
test.t2.i
from
test.t2
union all
select
'test.t3',
test.t3.i
from
test.t3
When putting all of this in a stored procedure, you can use PREPARE and EXECUTE to execute this created statement.
Above is just an example of an SQL statement, you should change it to your needs.

Add a column if it doesn't exist in mysql, need a little help debugging

I have the following query that I want to use to check whether if a column exists and then insert it if it doesn't.
$new_field ="IF NOT EXISTS
(SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = 'dashboard'
AND TABLE_NAME = '".$this->table_name."'
AND COLUMN_NAME = 'timestamp')
BEGIN
ALTER TABLE `".$this->table_name."`
ADD mytimestamp DATETIME NOT NULL AFTER day_chan3";
I am not sure where my mistake is as I am not that good at sql queries and I would really aprpeciate the help. I know this looks very n00b and i am one.
I made the changes mentioned in the comment and I echoed the output of my query,
IF NOT EXISTS
(SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dashboard'
AND TABLE_NAME = 'admin_tmp' AND COLUMN_NAME = 'timestamp')
BEGIN ALTER TABLE `admin_tmp` ADD mytimestamp DATETIME NOT NULL AFTER day_chan3
Your if statement is mixing up backticks with single quotes. Use backticks only when necessary and only for identifiers (column names and table names). Use single quotes only for string and date constant values. So, try this:
(SELECT *
FROM information_schema.COLUMNS
WHERE
TABLE_SCHEMA = 'dashboard'
-----------------------------^ --------^
AND TABLE_NAME = '".$this->table_name."'
---------------------------^ --------------------^
AND COLUMN_NAME = 'timestamp')
----------------------------^ --------^

MYSQL How to alter table if column doesnt exist

I am using SQL which doesnt support INFORMATION_SCHEMA.COLUMNS. My code, which doesnt work
ALTER TABLE Report ADD IF NOT EXISTS LastName CHAR(25);
this works
ALTER TABLE Report ADD LastName CHAR(25);
which part is wrong?
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Report' AND COLUMN_NAME = 'LastName' )
ALTER TABLE 'Report' ADD 'LastName' CHAR(25);
You need to quote the object names in the statement.
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Report' AND COLUMN_NAME = 'LastName' )
ALTER TABLE MLReport ADD LastName CHAR(25);

Changing multiple column names in a mysql table

I have many columns in a table with a name starting with field_t and I have to change that to field_c
For example, here is the ALTER TABLE statement for changing the name of one of the columns:
ALTER TABLE my_table CHANGE field_t_class field_c_class longtext;
How can I change all the columns that follow this pattern instead of doing it in a one by one basis?
You can generated the ALTERs like this
SELECT
CONCAT(
'ALTER TABLE ', C.TABLE_NAME, ' CHANGE ',
C.COLUMN_NAME, ' ', REPLACE(C.COLUMN_NAME, 'field_t', 'field_c')
)
FROM
INFORMATION_SCHEMA.COLUMNS C
WHERE
C.COLUMN_NAME LIKE 'field[_]t[_]%';
You'll also need to append DATA_TYPE etc and based on this CHARACTER_MAXIMUM_LENGTH,
NUMERIC_PRECISION, NUMERIC_SCALE, CHARACTER_SET_NAME and COLLATION_NAME...
Get 1st column names having name like 'field_t%';
select C.COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS C
WHERE
C.TABLE_NAME='YourTableName' AND C.COLUMN_NAME like 'field_t%';
Then make string of renaming column names like:
Make rename_string as:
rename_string= "RENAME COL1 to ReCol1
RENAME COL2 to ReCol2"
Then do :
ALTER Table YourTableName {rename_string};

Getting table metadata in MySQL

I'm trying to find out how to get the following constraint information from a table in MySQL 5.0:
primary key
foreign keys and table references
unique columns
What is the syntax of the query or queries to do so? I have a feeling I'm close with this, but there is no example.
For MySQL:
1) get Table/Fields metadata
SELECT table_schema, table_name, column_name, ordinal_position, data_type,
numeric_precision, column_type, column_default, is_nullable, column_comment
FROM information_schema.columns
WHERE (table_schema='schema_name' and table_name = 'table_name')
order by ordinal_position;
OR
show fields from 'table_name'
2) get Foregn Keys referenced table
SELECT `REFERENCED_TABLE_NAME`
FROM `information_schema`.`KEY_COLUMN_USAGE`
WHERE
`TABLE_NAME` = 'table_name' AND
`COLUMN_NAME` = 'Column_Name'
3) get indexes (primary and foreign) for a table
show keys from `table_name`
5) get All indexes and referreced table
SELECT *
FROM `KEY_COLUMN_USAGE`
WHERE
`TABLE_NAME` = 'table_name' AND
`TABLE_SCHEMA` = 'schema_name'
OR
SELECT *
FROM `REFERENTIAL_CONSTRAINTS`
WHERE
`TABLE_NAME` = 'table_name' AND
`CONSTRAINT_SCHEMA` = 'schema_name'
6) get STORED PROCEDURES
SELECT *
FROM `ROUTINES`
WHERE
`ROUTINE_SCHEMA` = 'schema_name'
7) get TRIGGERS
SELECT *
FROM `TRIGGERS`
WHERE
`TRIGGER_SCHEMA` = 'schema_name'
8) get EVENTS
SELECT *
FROM `EVENTS`
WHERE
`EVENT_SCHEMA` = 'schema_name'
9) get VIEWS
SELECT *
FROM `VIEWS`
WHERE
`TABLE_NAME` = 'table_name' AND
`TABLE_SCHEMA` = 'schema_name'
The SHOW COLUMNS command will show you the primary key and unique columns for a table.
As for foreign keys, you could use something like the SHOW CREATE TABLE command which will output the DDL statements needed to replicate the table.
Use
show fields from table_name
show keys from table_name
to get primary keys, foreign keys, unique, etc.
to get the table referenced by a foreign key use:
SELECT `REFERENCED_TABLE_NAME`
FROM `information_schema`.`KEY_COLUMN_USAGE`
WHERE
`TABLE_NAME` = '[table_containing_foreign_key]' AND
`COLUMN_NAME` = '[foreign_key]'
substituting [table_containing_foreign_key] and [foreign_key] with your values
use the following to get the same using Select Query:
SELECT table_schema, table_name, column_name, ordinal_position, data_type, numeric_precision, column_type FROM information_schema.columns WHERE table_name = '[TABLE_NAME]';
You should try it and see. INFORMATION_SCHEMA is part of some standard and is supported in a (mostly) similar way in other databases; this standard should be documented - you can look for that doc.
But mainly the way would be to create a bunch of test tables, and then have a look at INFORMATION_SCHEMA to see what's there.