Let's say that I have table with A LOT of columns. I have one column with primary key that has autoincrement set to 1. I want to insert a new row and in this new row I have following requirements:
The row must have generated ID
All non-specified columns have to be copied from row with id='9999'
I have to be able to set some values of columns by hand (for example columns name and age
I have tried:
Insert Into demo_table
Select * From demo_table Where id='9999';
However, I get this error:
An explicit value for the identity column in table 'demo_table' can only be specified when a column list is used and IDENTITY_INSERT is ON.
What do I need:
I want to duplicate a row -> let the id be set by database (I have PK and autoincrement configured) -> set some columns by hand -> have other column's values duplicated, without specifying column names (as I have a lot of columns and their names could change in future.)
Form of solution:
I would prefer if I was able to achive this using only one query. If necessary, I have stored procedures available.
My question:
Is this even possible? How could I achive such query/procedure?
There is a way to build sql query by table schema:
USE <databaseName>
DECLARE
#SourceTableName NVARCHAR(255) = <TableName>,
#SqlQuery NVARCHAR(MAX)
IF OBJECT_ID('tempdb.dbo.#IdentityCols', 'U') IS NOT NULL
DROP TABLE #IdentityCols;
CREATE TABLE #IdentityCols(
ColumnName NVARCHAR(255)
)
INSERT INTO #IdentityCols
SELECT
--TABLE_NAME,
COLUMN_NAME
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1 AND TABLE_NAME = #SourceTableName
UNION
SELECT
--o.name,
c.name
FROM
sys.objects o inner join
sys.columns c on o.object_id = c.object_id
WHERE
c.is_identity = 1 AND o.name = #SourceTableName
--STRING_AGG in SQL SERVER 2017 and greater. As aproach for early versions is cursor or loop
SELECT #SqlQuery = 'SELECT ' + STRING_AGG(COLUMN_NAME, ',') + ' FROM ' + #SourceTableName
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME=#SourceTableName AND COLUMN_NAME NOT IN (Select ColumnName FROM #IdentityCols)
exec sp_executesql #SqlQuery
For more information you can see this questions:
How can I show the table structure in SQL Server query?
How do you determine what SQL Tables have an identity column programmatically
How to concatenate text from multiple rows into a single text string in SQL Server
SQL Server Loop through Table Rows without Cursor
SQL Server loop - how do I loop through a set of records
For anyone interested, how I've solved this problem:
After I've read your comments (thanks btw) and some threads online, I've realized why I cannot do what I asked. However, I've come seen solution to similar problem somewhere, where they wanted to select * except one specific column, they solved it like this:
copied the entire table
selected from there.
I've come up with similar solution to my problem
-- check data, remove after testing
select * from demo_table order by ID desc;
-- create table with one column I want to duplicate
select * into Temp_demo_table from demo_table where ID=9999;
-- drop id, so it does not get included in the inter-table insert
alter table Temp_demo_table
drop column ID;
-- update columns that I need to modify, doesn't have to have WHERE clause, becuase there's only one row there
update Temp_demo_table set MyCustomProperty='abc', name=NULL, age=NULL
-- insert the desired and edited row
insert into demo_table
select * from Temp_demo_table;
-- drop the temp table
drop table Temp_demo_table;
-- check data, remove after testing
select * from demo_table order by ID desc;
I realize how inefficient this is, however the function (on my api) executing this command will not be called so often (max 100 times per day). I believe that this query could be optimized, however I do not have sufficient knowledge to do it at this moment (100% going to put it in my TODO :D).
Edit-1:
Just found out that you can write queries in oracle db like this:
(select * from demo_table) - (select name, age from demo_table)
I currentlly don't know if I can apply this to sql server, however as soon as I have an access to mssql, I'll try it out and keep this answear updated!
In one db i have table PRODUCTS with columns NAME and TECHNICAL_NAME.
In second database I have table TEMP_PRODUCTS with columns NAME (that corresponds to column NAME of the table PRODUCTS from the 1st db) and TECHNICAL_NAME that is null and that should be updated with the corresponding TECHNICAL_NAME values from 1st db.
So I should do UPDATE table TEMP_PRODUCTS by using JOIN with columns NAME?
I would like to avoid solution with exporting table from 1st bd and importing it to the 2nd db.
How can I do this?
By Creating the DB Link only we can access the one DB objects from another DB.
CREATE DATABASE LINK db1_link
CONNECT TO <User Name> IDENTIFIED BY <pwd>
USING 'db2';
-- db2 means Service Name for exp products db
Then Update Statement
UPDATE temp_products tp
SET technical_name=
(SELECT technical_name FROM products#db1_link p
WHERE tp.name = p.name)
Assuming:
both NAME columns are UNIQUE;
you have a database link in db2 pointing to db1.
UPDATE temp_products tp
SET technical_name=
(SELECT technical_name FROM products#db1 p
WHERE tp=name=p.name)
You need to execute the below query in db2 ,where temp_product table lies,and db link db1 on the same database db2,to connect db1.
MERGE temp_products tp
USING products#db1 pp
ON(tp.name = pp.name)
WHEN MATCHED THEN
UPDATE SET tp.technical_name = pp.technical_name;
You need to create a db link in database db2,so that you can connect to db1 ,to acces product table.
Please find the syntax for creating db link
CREATE [PUBLIC] DATABASE LINK <link_name>
CONNECT TO <user_name>
IDENTIFIED BY <password>
USING '<service_name>';
How to change column order in a table using SQL query in SQL Server 2005?
I want to rearrange column order in a table using SQL query.
You cannot. The column order is just a "cosmetic" thing we humans care about - to SQL Server, it's almost always absolutely irrelevant.
What SQL Server Management Studio does in the background when you change column order there is recreating the table from scratch with a new CREATE TABLE command, copying over the data from the old table, and then dropping it.
There is no SQL command to define the column ordering.
You have to explicitly list the fields in the order you want them to be returned instead of using * for the 'default' order.
original query:
select * from foobar
returns
foo bar
--- ---
1 2
now write
select bar, foo from foobar
bar foo
--- ---
2 1
according to https://learn.microsoft.com/en-us/sql/relational-databases/tables/change-column-order-in-a-table
This task is not supported using Transact-SQL statements.
Well, it can be done, using create/ copy / drop/ rename, as answered by komma8.komma1
Or you can use SQL Server Management Studio
In Object Explorer, right-click the table with columns you want to reorder and click Design (Modify in ver. 2005 SP1 or earlier)
Select the box to the left of the column name that you want to reorder. (You can select multiple columns by holding the [shift] or
the [ctrl] keys on your keyboard.)
Drag the column(s) to another location within the table.
Then click save. This method actually drops and recreates the table, so some errors might occur.
If Change Tracking option is enabled for the database and the table, you shouldn't use this method.
If it is disabled, the Prevent saving changes that require the table re-creation option should be cleared in Tools menu > Options > Designers, otherwise "Saving changes is not permitted" error will occur.
Disabling the Prevent saving changes that require the table re-creation option is strongly advised against by Microsoft, as it leads to the existing change tracking information being deleted when the table is re-created, so you should never disable this option if Change Tracking is enabled!
Problems may also arise during primary and foreign key creation.
If any of the above errors occurs, saving fails which leaves you with the original column order.
In SQLServer Management Studio:
Tools -> Options -> Designers -> Table and Database Designers
Unselect 'Prevent saving changes that require table re-creation'.
Then:
right click the table you want to re-order the columns for.
click 'Design'.
Drag the columns to the order you want.
finally, click save.
SQLServer Management studio will drop the table and recreate it using the data.
This is similar to the question on ordering the records in the result of a query .. and typically no one likes the formally correct answer ;-)
So here it goes:
as per SQL standard, the columns in a table are not "ordered"
as a result, a select * does not force the columns to be returned in a particular order
typically, each RDBMS has a kind of "default" order (usually the order that the columns were added to the table, either in the create table' or in thealter table add ` statements
therefore, if you rely on the order of columns (because you are using the results of a query to poulate some other datastructure from the position of the columns), explicitly list the columns in the order you want them.
You can of course change the order of the columns in a sql statement. However if you want to abstract tables' physical column order, you can create a view. i.e
CREATE TABLE myTable(
a int NULL,
b varchar(50) NULL,
c datetime NULL
);
CREATE VIEW vw_myTable
AS
SELECT c, a, b
FROM myTable;
select * from myTable;
a b c
- - -
select * from vw_myTable
c a b
- - -
You can do it by creating a new table, copy all the data over, drop the old table, then renaming the new one to replace the old one.
You could also add new columns to the table, copy the column by column data over, drop the old columns, then rename new columns to match the old ones. A simple example below:
http://sqlfiddle.com/#!3/67af4/1
CREATE TABLE TestTable (
Column1 INT,
Column2 VARCHAR(255)
);
GO
insert into TestTable values(1, 'Test1');
insert into TestTable values(2, 'Test2');
GO
select * from TestTable;
GO
ALTER TABLE TestTable ADD Column2_NEW VARCHAR(255);
ALTER TABLE TestTable ADD Column1_NEW INT;
GO
update TestTable
set Column1_NEW = Column1,
Column2_NEW = Column2;
GO
ALTER TABLE TestTable DROP COLUMN Column1;
ALTER TABLE TestTable DROP COLUMN Column2;
GO
sp_rename 'TestTable.Column1_NEW', 'Column1', 'COLUMN';
GO
sp_rename 'TestTable.Column2_NEW', 'Column2', 'COLUMN';
GO
select * from TestTable;
GO
In SQLServer Management Studio:
Tools -> Options -> Designers -> Table and Database Designers
Unselect Prevent saving changes that require table re-creation.
Now you can reorder the table.
Sql server internally build the script. It create a temporary table with new changes and copy the data and drop current table then recreate the table insert from temp table. I find it from "Generate Change script" option ssms 2014. Script like this. From Here: How to change column order in a table using sql query
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Tmp_emps
(
id int NULL,
ename varchar(20) NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Tmp_emps SET (LOCK_ESCALATION = TABLE)
GO
IF EXISTS(SELECT * FROM dbo.emps)
EXEC('INSERT INTO dbo.Tmp_emps (id, ename)
SELECT id, ename FROM dbo.emps WITH (HOLDLOCK TABLOCKX)')
GO
DROP TABLE dbo.emps
GO
EXECUTE sp_rename N'dbo.Tmp_emps', N'emps', 'OBJECT'
GO
COMMIT
If your table has enough columns then you can try this. First create a new table with preferred order of columns.
create table new as select column1,column2,column3,....columnN from table_name;
Now drop the table using drop command
drop table table_name;
now rename the newly created table to your old table name.
rename new to table_name;
now select the table, you have your columns rearranged as you preferred before.
select * from table_name;
Not sure if still relevant, but SSMS can generate a change scripts for this.
Re-order (drag the column) the table in Designer View
Click on 'Generate Change Script'
The generated script contains the script which does the following:
Create a temporary table
Adds the constraints, relationships and triggers from original table to temporary table
Drop original table
Rename temporary table to original table name
If you have not yet added any data into your table yet, there is one way to move the columns around.
Try this:
In SSMS, click Tools > Options > Designers > Table and Database Designers > Uncheck the box next to Prevent saving changes that require table re-creation > Click OK.
In the object tree, right-click on your table and select Design > in the thin column to the left of the Column Name column, you can click and drag the columns around to wherever you want them. When you're done, just go to close the Design tab and SSMS will ask you if you want to save your changes, click OK.
Optional:
3. Re-enable the checkbox for the option from Step 1 to re-secure your table.
Hope this helps someone!
Credit goes to Microsoft:
https://learn.microsoft.com/en-us/troubleshoot/sql/ssms/error-when-you-save-table#more-information
At the end of the day, you simply cannot do this in MS SQL. I recently created tables on the go (application startup) using a stored Procedure that reads from a lookup table. When I created a view that combined these with another table I had manually created earlier one (same schema, with data), It failed - simply because I was using ''Select * UNION Select * ' for the view. At the same time, if I use only those created through the stored procedure, I am successful.
In conclusion: If there is any application which depends on the order of column it is really not good programming and will for sure create problems in the future. Columns should 'feel' free to be anywhere and be used for any data process (INSERT, UPDATE, SELECT).
You can achieve it with these steps:
remove all foreign keys and primary key of the original table.
rename the original table.
using CTAS create the original table in the order you want.
drop the old table.
apply all constraints back to the original table
If the columns to be reordered have recently been created and are empty, then the columns can be deleted and re-added in the correct order.
This happened to me, extending a database manually to add new functionality, and I had missed a column out, and when I added it, the sequence was incorrect.
After finding no adequate solution here I simply corrected the table using the following kind of commands.
ALTER TABLE tablename DROP COLUMN columnname;
ALTER TABLE tablename ADD columnname columntype;
Note: only do this if you don't have data in the columns you are dropping.
People have said that column order does not matter. I regularly use SQL Server Management Studio "generate scripts" to create a text version of a database's schema. To effectively version control these scripts (git) and to compare them (WinMerge), it is imperative that the output from compatible databases is the same, and the differences highlighted are genuine database differences.
Column order does matter; but just to some people, not to everyone!
Use
SELECT * FROM TABLE1
which displays the default column order of the table.
If you want to change the order of the columns.
Specify the column name to display correspondingly
SELECT COLUMN1, COLUMN5, COLUMN4, COLUMN3, COULMN2 FROM TABLE1
you can use indexing.. After indexing, if select * from XXXX results should be as per the index, But only result set.. not structrue of Table
In order to have a specific column order You need to select column by column in the order You wish.
Selection order dictates how columns will be ordered in output.
Try this command:
alter table students modify age int(5) first;
This will change the position of age to the first position.
You can change this using SQL query. Here is sql query to change the sequence of column.
ALTER TABLE table name
CHANGE COLUMN `column1` `column1` INT(11) NOT NULL COMMENT '' AFTER `column2`;
alter table name modify columnname int(5) first;
will bring the column to first
alter table name modify columnname int(5) after (tablename);
This worked for me on Oracle DB:
select column1, column2, t.* from table t
Example: Change position of field_priority after field_price in table status.
ALTER TABLE `status` CHANGE `priority` `priority` INT(11) NULL DEFAULT NULL AFTER `price`;