Copy column definition from one table to another? - mysql

I want to copy a column (definition, not data) from one table to another. Add the column if it doesn't exist in destination table, or better yet, modify it accordingly if it exists.
Tried to google but everything seems to be about either copying the data rather than the definition, or about copying an entire table using CREATE TABLE ... LIKE ....
Thus far the closest I could find is this:
CREATE TABLE table2 AS
SELECT field4, field7 -- only the columns you want
FROM table
WHERE FALSE; -- and no data
But I need to copy columns to existing tables. So I tried:
ALTER TABLE table2 AS
SELECT field4, field7 -- only the columns you want
FROM table
WHERE FALSE; -- and no data
But apparently it refused to work.
Is there something like this?
ALTER TABLE table1 ADD COLUMN column2 LIKE table2.column5
Any way to achieve this in MySQL?

The best way is to Dump the table and then you can use ALTER command to create the new table.
Dumping the table gives back the query to CREATE the table.
CREATE TABLE IF NOT EXISTS customer (
id int(11) NOT NULL AUTO_INCREMENT,
customerId varchar(50) NOT NULL,
firstName varchar(30) NOT NULL,
middleName varchar(30) DEFAULT NULL,
lastName varchar(30) CHARACTER SET utf8 COLLATE utf8_estonian_ci DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
USE the same to ALTER an existing table, (say customerinfo)
`ALTER TABLE customerinfo ADD COLUMN (
customerId varchar(50) NOT NULL,
firstName varchar(30) NOT NULL,
middleName varchar(30) DEFAULT NULL,
lastName varchar(30) CHARACTER SET utf8 COLLATE utf8_estonian_ci DEFAULT NULL
)

If you want to do it with queries this is the way:
Get the properties of the old column with:
SHOW COLUMNS FROM `mytable` where Field=`mycolumn`
Use mysqli_fetch_array to get the field properties in the variable $row.
Now create the new query:
$qry = "ALTER TABLE othertable";
$qry .= " ADD `newcol`"; /* name of new column; $row['Field'] works too */
$qry .= " ".$row["Type"]; /* example value: varchar(255) */
if($row["Null"] == "NO")
$qry .= " NOT NULL";
if($row["Default"] != "")
$qry .= " default '".$row["Default"]."'";
The $row contains also an Extra field but that can give problems with auto_increase.

Related

modify enum values in migrations scripts

Is there a correct and safe way to modify enum column type values? Add new or remove old.
E.g.: I have ENUM ("apple", "banana")
I have 2 tasks that need to add value to the ENUM. 1 needs to add orange and second needs to add peach.
If I get migrations scripts, I will have:
ALTER TABLE example MODIFY COLUMN fruit ENUM("apple", "banana", "orange) NOT NULL
ALTER TABLE example MODIFY COLUMN fruit ENUM("apple", "banana", "peach) NOT NULL
I will end up only with values from the last executed SQL. Is there a way to just add value to existing values?
You can use the show or description command.
show create table dl_stats
produces this on my system if I use print_r to show the row fetched from the database.
Array
(
[Table] => dl_stats
[Create Table] => CREATE TABLE `dl_stats` (
`Ref` bigint(20) NOT NULL AUTO_INCREMENT,
`Area` varchar(10) NOT NULL,
`Name` varchar(80) NOT NULL,
`WIN` bigint(20) NOT NULL DEFAULT 0,
`AND` bigint(20) NOT NULL DEFAULT 0,
`LNX` bigint(20) NOT NULL DEFAULT 0,
`IOS` bigint(20) NOT NULL DEFAULT 0,
`MOS` bigint(20) NOT NULL DEFAULT 0,
`MSC` bigint(20) NOT NULL DEFAULT 0,
PRIMARY KEY (`Ref`),
UNIQUE KEY `By_Name` (`Area`,`Name`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4
)
Once you have this in a variable in your language, you can parse it.
13.7.7.10 SHOW CREATE TABLE Statement
SHOW CREATE TABLE tbl_name
Shows the CREATE TABLE statement that creates the named table. To use this
statement, you must have some privilege for the table. This statement
also works with views.
From dev.mysql.com
More examples are at tutorialspoint.com
EDIT
If you want it all sql then you need to write a procedure to do it which you call from your script. This can fetch the enum value from the information_schema.
I added a column test just for testing type enum with values 'a','b','c','d' to one of my tables.
Here's a function to demo the concept. To check what is returned by the select statement. Replace the TABLE_SCHEMA, TABLE_NAME and COLUMN_NAME values to suit.
CREATE DEFINER=`root`#`localhost`
FUNCTION `Get_Def`(`New_Value` VARCHAR(40)) RETURNS LONGTEXT
CHARSET utf8mb4 NOT DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER
return (select COLUMN_TYPE
from information_schema.`COLUMNS`
where TABLE_SCHEMA = 'aklcity_directory'
and TABLE_NAME = 'entries'
and COLUMN_NAME = 'Test')
This returns
enum('a','b','c','d')
In your procedure you can get this value as a string (more accurately longtext). You can check if the new value exists. If not, you can add it in.
To add the value 'e' to it requires
ALTER TABLE `entries` CHANGE `Test` `Test`
ENUM('a','b','c','d','e')
CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;
Please alter to suit.

Hash of two columns in mysql

I have a MYSQL table, with 5 columns in it:
id bigint
name varchar
description varchar
slug
Can I get MySQL to automatically generate the value of slug as a 256 Bit Hash of name+description?
I am now using PHP to generate an SHA256 value of the slug prior to saving it.
Edit:
By automatic, I mean see if it's possible to change the default value of the slug field, to be a computed field that's the sha256 of name+description.
I already know how to create it as part of an insert operation.
MySQL 5.7 supports generated columns so you can define an expression, and it will be updated automatically for every row you insert or update.
CREATE TABLE IF NOT EXISTS MyTable (
id int NOT NULL AUTO_INCREMENT,
name varchar(50) NOT NULL,
description varchar(50) NOT NULL,
slug varchar(64) AS (SHA2(CONCAT(name, description), 256)) STORED NOT NULL,
PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;
If you use an earlier version of MySQL, you could do this with TRIGGERs:
CREATE TRIGGER MySlugIns BEFORE INSERT ON MyTable
FOR EACH ROW SET slug = SHA2(CONCAT(name, description));
CREATE TRIGGER MySlugUpd BEFORE UPDATE ON MyTable
FOR EACH ROW SET slug = SHA2(CONCAT(name, description), 256);
Beware that concat returns NULL if any one column in the input is NULL. So, to hash in a null-safe way, use concat_ws. For example:
select md5(concat_ws('', col_1, .. , col_n));
Use MySQL's CONCAT() to combine the two values and SHA2() to generate a 256 bit hash.
CREATE TABLE IF NOT EXISTS `mytable` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`description` varchar(50) NOT NULL,
`slug` varchar(64) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `mytable` (`name`,`description`,`slug`)
VALUES ('Fred','A Person',SHA2(CONCAT(`name`,`description`),256));
SELECT * FROM `mytable`
OUTPUT:
COLUMN VALUE
id 1
name Fred
description A Person
slug ea76b5b09b0e004781b569f88fc8434fe25ae3ad17807904cfb975a3be71bd89
Try it on SQLfiddle.

Creating a trigger that pulls information from another table in phpMyAdmin

I am trying to create a fairly complicated Trigger and I'm not sure if it can be done on phpMyAdmin.
Right now I have this query that creates a table with all the information I need from it.
CREATE TABLE SeniorDB_Shipping
SELECT
SeniorDB_Invoice.ID_Order,
SeniorDB_Customer.MCT_Code,
SeniorDB_Customer.Customer_Name,
SeniorDB_Customer.Customer_Address,
SeniorDB_Customer.Customer_City,
SeniorDB_Customer.Customer_State,
SeniorDB_Invoice.Shipping_Company
FROM SeniorDB_Customer
Join SeniorDB_Invoice ON SeniorDB_Customer.MCT_Code = SeniorDB_Invoice.MCT_Code
As you can see in the image, when I run the query, it pulls in information from the tables above the information. I'm trying (and failing) to create a trigger that will do this same thing without having to create a brand new table every single time. All the other posts I have seen are similar in regards to creating a table instead of inserting to a table.
What the trigger does is, when I enter the ID_Order, the rest of the information will get pulled from the database.
This is the trigger I have so far:
delimiter ~
create trigger SeniorDB_Shipping before insert on SeniorDB_Shipping
for each row begin
set new.SeniorDB_Shipping.MCT_Code = new.SeniorDB_Customer.MCT_Code,;
set new.SeniorDB_Shipping.Customer_Name = new.SeniorDB_Customer.Customer_Name,;
set new.SeniorDB_Shipping.Customer_Address = new.SeniorDB_Customer.Customer_Address,;
set new.SeniorDB_Shipping.Customer_City = new.SeniorDB_Customer.Customer_City,;
set new.SeniorDB_Shipping.Customer_State = new.SeniorDB_Customer.Customer_State,;
set new.SeniorDB_Shipping.Shipping_Company = new.SeniorDB_Customer.Shipping_Company,;
end~
delimiter ;
I feel like I'm right there. I just can't link it to when I enter the ID_Order.
This is the page if you would like to see the databases: http://polonium.forest.usf.edu/~sngamwon/SeniorProject/SeniorDB_Order.php
Ok, so you'll need to run this once:
/* Create the table with a primary key */
create table `SeniorDB_Shipping` (
`id` INT unsigned AUTO_INCREMENT NOT NULL,
primary key(id),
`ID_Order` int NOT NULL,
`MCT_Code` int NOT NULL,
`Customer_Name` varchar(255) NOT NULL,
`Customer_Address` varchar(255) NOT NULL,
`Customer_City` varchar(255) NOT NULL,
`Customer_State` varchar(255) NOT NULL,
`Shipping_Company` varchar(255) NOT NULL
) ENGINE=MyISAM CHARACTER SET=utf8 COLLATE utf8_general_ci;
Then you can run
/* Insert statement */
INSERT INTO `SeniorDB_Shipping` (
`ID_Order`,
`MCT_Code`,
`Customer_Name`,
`Customer_Address`,
`Customer_City`,
`Customer_State`,
`Shipping_Company`
) SELECT
invoice.ID_Order,
customer.MCT_Code,
customer.Customer_Name,
customer.Customer_Address,
customer.Customer_City,
customer.Customer_State,
invoice.Shipping_Company
FROM
SeniorDB_Customer as customer
Join SeniorDB_Invoice as invoice
ON customer.MCT_Code = invoice.MCT_Code;
I've run this in my own PHPMyAdmin, so it works. But I obviously don't have your schema. Known issues:
This will populate SeniorDB_Shipping with ALL the data from your two tables each time. Modify the query as required to select only recent data if that's not what you want. If ID_Order is a primary key you could check that doesn't already exist.

Copy/duplicate SQL row with blob/text, How do that?

I would like to copy a SQL's row into the same table.
But in my table, I've a 'text' column.
With this SQL:
CREATE TEMPORARY TABLE produit2 ENGINE=MEMORY SELECT * FROM produit WHERE pdt_ID = 'IPSUMS';
UPDATE produit2 SET pdt_ID='ID_TEMP';
INSERT INTO produit SELECT * FROM produit2;
DROP TABLE produit2;
I get this error :
#1163 - The used table type doesn't support BLOB/TEXT columns
Here is my table :
pdt_ID varchar(6)
pdt_nom varchar(130)
pdt_stitre varchar(255)
pdt_accroche varchar(255)
pdt_desc text
pdt_img varchar(25)
pdt_pdf varchar(10)
pdt_garantie varchar(80)
edit_ID varchar(7)
scat_ID int(11)
pdt_asso1 char(3)
pdt_asso2 char(3)
pdt_online tinyint(4)
It's possible to help me to duplicate row ? How?
You can't store TEXT-columns (which really are blobs) in memory tables. See here
Depending on your ultimate goal, you may insert a md5-hash of the TEXT-column instead to preserve entity identity. Otherwise you need to put pdt_desc and such into another table and refer to it's primary key - that will save you some storage/memory too.

How to copy a field from a table paste into another table with same properties

I am searching this for hours.
I just want to copy some fields from one table into an another table. In the destination table the fields i want to copy doesn't exsist.
It's like, copy and paste.
Ex. I have to tables
Table A Like
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`active` int(11) DEFAULT '0'
Table B like
`date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`alias` varchar(255) DEFAULT NULL,
`voters` int(11) DEFAULT NULL,
`level` int(11) NOT NULL DEFAULT '0',
`content` text
Ex. I want to copy 'content , level, voters' from Table B to Table A with the same structure and data.
I have in my mind like this, But HOW?
Alter Table A Add content (same SCHEMA as TABLE B.content)
Alter Table A Add level (same SCHEMA as TABLE B.level)
Alter Table A Add level (voters SCHEMA as TABLE B.voters)
INSERT INTO A (col1 , col2 , col3)
SELECT colB1, colB2,colB3
FROM B
they must be that same datatype and size
UPDATE
if table A does not contain data you can create it like this
CREATE TABLE A LIKE B;
Use LIKE to create an empty table based on the definition of another table, including any column attributes and indexes defined in the original table:
then make the insert statement above
if you want to keep the data in table A and add some columns from table B you can merge these two table inside new Table X then you delete table A and rename X
CREATE TABLE X
SELECT * from emp;
Note: if table A contains many record this will take too much time and is not a good solution
but your select statement will contains join , if there is a relationship between A and B tell me to write a more specific solution