"CONCAT"enated column not showing up in database table - mysql

I tried concat function to combine two columns, i got the output also but
my question is why i don't see new column being added to the table. Is concatenating is just a temporary result?
SELECT CONCAT(Name,',',Continent)AS new_address FROM Country

If you want to add a column to the table, you need to alter the table:
alter table country add new_address varchar(255);
Then you can set the value using update:
update country
set new_address = concat_ws(' ', name, continent);
I prefer concat_ws() for this type of operation because it does not return NULL if one of the columns is NULL.
Note: The table has the "correct" values after the update. But, subsequent changes to the table might require that you re-run the update or that you use a trigger to maintain consistency.
On best practice is to define a view to do the calculation:
create view v_country as
select c.*, concat_ws(' ', name, continent) as new_address
from country;
When you access the data through the view, the new_address field will always be correct.

Yes this creates a column that only exists in your SELECT query.
It certainly does not alter the underlying table.
If you wanted to add this computation to the underlying table you could add a generated column as of MySQL 5.7.6.
CREATE TABLE Country
(
Name VARCHAR(100) NOT NULL,
Continent VARCHAR(100) NOT NULL
);
INSERT INTO Country
VALUES ('France', 'Europe'),
('Nigeria','Africa');
ALTER TABLE Country
ADD new_address VARCHAR(201) AS (CONCAT(Name,',',Continent));
SELECT *
FROM Country;
Online Demo

Related

Two autoincrements columns or autoincrement and same value in other column

I need two columns in table that would have same value on insert. Is there any way to do it from database side?
So you want to let one column use the auto_increment feature, but make another column in the same table also have the same value?
I can't think of a reason you would need this feature. Perhaps you could explain what you're trying to accomplish, and I can suggest a different solution?
A trigger won't work for this. It's a chicken-and-egg problem:
You can't change any column's value in an AFTER trigger.
But the auto-increment value isn't set yet when a BEFORE trigger executes.
It also won't work to use a MySQL 5.7 GENERATED column:
CREATE TABLE MyTable (
id INT AUTO_INCREMENT PRIMARY KEY,
why_would_you_want_this INT GENERATED ALWAYS AS (id)
);
ERROR 3109 (HY000): Generated column 'why_would_you_want_this'
cannot refer to auto-increment column.
You can't do it in a single SQL statement. You have to INSERT the row, and then immediately do an UPDATE to set your second column to the same value.
CREATE TABLE MyTable (
id INT AUTO_INCREMENT PRIMARY KEY,
why_would_you_want_this INT
);
INSERT INTO MyTable () VALUES ();
UPDATE MyTable SET why_would_you_want_this = LAST_INSERT_ID()
WHERE id = LAST_INSERT_ID();
You could alternatively generate the ID value using some other mechanism besides AUTO_INCREMENT (for example a Memcached incrementing key). Then you could insert the new value in both columns:
INSERT INTO MyTable (id, why_would_you_want_this) VALUES ($gen_id, $gen_id);
Define a before or after insert trigger and assign the value of the 2nd field in the trigger.
If the 1st field is an auto increment column, then you need to use an after insert trigger. If your application assigns value to the 1st field, then you can use a before insert trigger.
However, I would no necessarily duplicate the value on insert. You can leave the 2nd field as null on insert, which would mean that its value is the same as the 1st field's. The only drawback of this approach is that it may be more difficult to create joins on the 2nd field.
You can do this in one query by using the primary key (assumed to be id) and setting your column (assumed to be columnName):
"INSERT INTO tableName SET `columnName` = (SELECT MAX(x.id) FROM tableName x)+1"
This will not work if you have deleted the most recent primary key row however. To get past this, you can insert into the id as well:
"INSERT INTO tableName SET `columnName` = (SELECT MAX(x.id) FROM tableName x)+1, `id`= (SELECT MAX(x.id) FROM tableName x)+1"
However, this solution has the downside (or upside depending on the case) of reusing primary key values that have already been deleted.
suggested way:
To use the actual auto_increment value, you can do this:
"INSERT INTO tableName SET `columnName` = (SELECT `AUTO_INCREMENT` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'db_name' AND TABLE_NAME = 'table_name')"
Sources that helped me solve this: Prashant Pimpale's answer

Store records in a new table created by a query in mysql

I have two tables ,location and locationdata. I want to query data from both the tables using join and to store the result in a new table(locationCreatedNew) which is not already present in the MySQL.Can I do this in MySQL?
SELECT location.id,locationdata.name INTO locationCreatedNew FROM
location RIGHT JOIN locationdata ON
location.id=locationdata.location_location_id;
Your sample code in OP is syntax in SQL Server, the counter part of that in MySQL is something like:
CREATE TABLE locationCreatedNew
SELECT * FROM location RIGHT JOIN locationdata
ON location.id=locationdata.location_location_id;
Referance: CREATE TABLE ... SELECT
For CREATE TABLE ... SELECT, the destination table does not preserve information about whether columns in the selected-from table are generated columns. The SELECT part of the statement cannot assign values to generated columns in the destination table.
Some conversion of data types might occur. For example, the AUTO_INCREMENT attribute is not preserved, and VARCHAR columns can become CHAR columns. Retrained attributes are NULL (or NOT NULL) and, for those columns that have them, CHARACTER SET, COLLATION, COMMENT, and the DEFAULT clause.
When creating a table with CREATE TABLE ... SELECT, make sure to alias any function calls or expressions in the query. If you do not, the CREATE statement might fail or result in undesirable column names.
CREATE TABLE newTbl
SELECT tbl1.clm, COUNT(tbl2.tbl1_id) AS number_of_recs_tbl2
FROM tbl1 LEFT JOIN tbl2 ON tbl1.id = tbl2.tbl1_id
GROUP BY tbl1.id;
NOTE: newTbl is the name of the new table you want to create. You can use SELECT * FROM othertable which is the query that returns the data the table should be created from.
You can also explicitly specify the data type for a column in the created table:
CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;
For CREATE TABLE ... SELECT, if IF NOT EXISTS is given and the target table exists, nothing is inserted into the destination table, and the statement is not logged.
To ensure that the binary log can be used to re-create the original tables, MySQL does not permit concurrent inserts during CREATE TABLE ... SELECT.
You cannot use FOR UPDATE as part of the SELECT in a statement such as CREATE TABLE new_table SELECT ... FROM old_table .... If you attempt to do so, the statement fails.
Please check it for more. Hope this help you.
Use Query like below.
create table new_tbl as
select col1, col2, col3 from old_tbl t1, old_tbl t2
where condition;

How to move columns in a MySQL table?

Currently I am having the following MySQL table: Employees (empID, empName, department);
I want to change the table to the following: Employees (empID, department, empName);
How can this be done using ALTER statements?
Note: I want to change only column positions.
If empName is a VARCHAR(50) column:
ALTER TABLE Employees MODIFY COLUMN empName VARCHAR(50) AFTER department;
EDIT
Per the comments, you can also do this:
ALTER TABLE Employees CHANGE COLUMN empName empName VARCHAR(50) AFTER department;
Note that the repetition of empName is deliberate. You have to tell MySQL that you want to keep the same column name.
You should be aware that both syntax versions are specific to MySQL. They won't work, for example, in PostgreSQL or many other DBMSs.
Another edit: As pointed out by #Luis Rossi in a comment, you need to completely specify the altered column definition just before the AFTER modifier. The above examples just have VARCHAR(50), but if you need other characteristics (such as NOT NULL or a default value) you need to include those as well. Consult the docs on ALTER TABLE for more info.
Change column position:
ALTER TABLE Employees
CHANGE empName empName VARCHAR(50) NOT NULL AFTER department;
If you need to move it to the first position you have to use term FIRST at the end of ALTER TABLE CHANGE [COLUMN] query:
ALTER TABLE UserOrder
CHANGE order_id order_id INT(11) NOT NULL FIRST;
phpMyAdmin provides a GUI for this within the structure view of a table.
Check to select the column you want to move and click the change action at the bottom of the column list.
You can then change all of the column properties and you'll find the 'move column' function at the far right of the screen.
Of course this is all just building the queries in the perfectly good top answer but GUI fans might appreciate the alternative.
my phpMyAdmin version is 4.1.7
I had to run this for a column introduced in the later stages of a product, on 10+ tables. So wrote this quick untidy script to generate the alter command for all 'relevant' tables.
SET #NeighboringColumn = '<YOUR COLUMN SHOULD COME AFTER THIS COLUMN>';
SELECT CONCAT("ALTER TABLE `",t.TABLE_NAME,"` CHANGE COLUMN `",COLUMN_NAME,"`
`",COLUMN_NAME,"` ", c.DATA_TYPE, CASE WHEN c.CHARACTER_MAXIMUM_LENGTH IS NOT
NULL THEN CONCAT("(", c.CHARACTER_MAXIMUM_LENGTH, ")") ELSE "" END ," AFTER
`",#NeighboringColumn,"`;")
FROM information_schema.COLUMNS c, information_schema.TABLES t
WHERE c.TABLE_SCHEMA = '<YOUR SCHEMA NAME>'
AND c.COLUMN_NAME = '<COLUMN TO MOVE>'
AND c.TABLE_SCHEMA = t.TABLE_SCHEMA
AND c.TABLE_NAME = t.TABLE_NAME
AND t.TABLE_TYPE = 'BASE TABLE'
AND #NeighboringColumn IN (SELECT COLUMN_NAME
FROM information_schema.COLUMNS c2
WHERE c2.TABLE_NAME = t.TABLE_NAME);
For those using TablePlus, you can just mark all tables, right click -> Copy, in the new table -> Paste.

How to explode mysql field value and use it in SELECT query

How can i explode field value of table in select query ?
for e.g. i have 1 field in table named "coordinates" which contains latitude , longitude.
Now i want to use this latitude and longitude in select query.
Can i separate this values and use it in select query ?
Firstly, the comments are correct: this is a violation of normal form. Always store separate data in separate columns - it will make your life easier.
If you try to write a select statement that parses the coordinates field and tries to filter on one or both halves, you will have a query that runs SUPER slowly, since an index on that column will not function. Instead, I would recommend writing a query to split that column into two, such as the following:
alter table `your_table`
add column `coordinate_x` int null;
alter table `your_table`
add column `coordinate_y` int null;
update `your_table`
set `coordinate_x` = substring(`coordinates`,1,locate(',',`coordinates`))
,`coordinate_y`= substring(`coordinates`,locate(',',`coordinates`)+1);
alter table `your_table`
drop column `coordinates`;
alter table `your_table`
modify column `coordinate_x` int not null;
alter table `your_table`
modify column `coordinate_y` int not null;
You could then index coordinate_x and coordinate_y to make your select statement run quickly.

MySQL inserting data only if table doesn't exist

Using strictly SQL (no PHP or anything else), is it possible to create a table and insert default data into that table only if that table doesn't exist?
Use the CREATE TABLE ... SELECT format:
create table if not exists tablename as
select * from defaultdata;
Here is one way of doing it:
CREATE TABLE IF NOT EXISTS T (
ID int(10) unsigned NOT NULL primary key,
NAME varchar(255) NOT NULL
);
REPLACE INTO T SELECT 1, 'John Doe';
REPLACE INTO T SELECT 2, 'Jane Doe';
REPLACE is a MySQL extension to the SQL standard that either inserts, or deletes and inserts.
You might do a select on the one of the meta data tables
if(not exists select * from whatever_meta where table_name = "whatever)
begin
...
end
You would have to do some research to figure out how exactly...
Can you store the table status as a variable, then use that variable to determine whether to insert data? Ex:
#status = SHOW TABLES LIKE 'my_table';
INSERT INTO my_table VALUES (1,'hello'),(2,'world') WHERE #status <> false;
The problem with Paul Morgan's answer is that it expects data to already exist in another table. Jonas' answer would be extremely resource exhaustive, especially if there's a lot of REPLACES (which are unnecessary if the table exists).
May be I am missing the point but why can't the default data be a set of insert statements...and what one simply needs to do is create the table if it does not exist followed by insert statements...that ways the default data does not have to exist in a different table.