Insert multiple rows of default values into a table - sql-server

I have a table with a single column, which is an auto-generated identity
create table SingleIdTable (
id int identity(1,1) not null
)
I can insert a single row with an auto-generated id with:
insert into SingleIdTable default values
I want to insert many rows and use the output syntax to get their ids, something like:
insert into SingleIdTable
output inserted.Id into #TableOfIds
select (default values) from SomeOtherTable where Attribute is null
Where the intention is to insert a row into SingleIdTable for each row in SomeOtherTable where Attribute is null using an auto-generated id. The above doesn't work, but how could I do it. I note that if my table had more than just a single column I could do it, but I can't select empty rows which is what I really want to do.
I can't change the definition of SomeOtherTable.

If SQL Server 2008+ you can use MERGE for this. Example syntax below.
MERGE INTO SingleIdTable
USING (SELECT *
FROM SomeOtherTable
WHERE Attribute IS NULL) T
ON 1 = 0
WHEN NOT MATCHED THEN
INSERT
DEFAULT VALUES
OUTPUT INSERTED.id;
I'm not sure what practical use this single column table has though?

you did not specify which version of SQL Server you are on. If you happen to be on SQL 2012 you probably can replace you SingleIdTable with a sequence: http://msdn.microsoft.com/en-us/library/ff878091.aspx

Related

Insert from temp table to a table with identity column

I'm grabbing some rows from a table, manipulating them in a temp table, and then looking to insert them as new rows into my original table.
However, I'm running into an issue with the identity column, even when I don't have the identity column on my temp table. The identity column is an auto-incrementing int.
This seems like a simple thing I'm way overthinking.
select top 0 *
into #TestTable
from OriginalTable;
...
--insert and manipulate records
...
ALTER TABLE #TestTable
DROP COLUMN MyIdentityColumn;
DECLARE #InsertedRows TABLE (NewSeqNum INT);
INSERT INTO OriginalTable
OUTPUT MyIdentityColumn INTO #InsertedRows(NewSeqNum)
SELECT * FROM #TestTable
but I get this error:
An explicit value for the identity column in table 'OriginalTable' can only be specified when a column list is used and IDENTITY_INSERT is ON.
I absolutely do not want to set an explicit value, I want it to insert and give me the new identity (via #InsertedRows)
If you don't want to keep the id of inserted records, then you need to specify all your columns but the id column in the select. As general good practice, dont select *, always specify the columns you want to retrieve-insert.
INSERT INTO OriginalTable (col1, col2, col3...)
OUTPUT MyIdentityColumn INTO #InsertedRows(NewSeqNum)
SELECT (col1, col2, col3...) FROM #TestTable
If I'm understanding you, I think your problem is that you're trying to insert '*' into the original table - which means all of your columns from the temp table. Including your ID column (which you don't want to insert, because you're wanting it to auto-generate.)
Instead, I'd suggest doing something like this:
Select [ColumnB],[ColumnC],[ColumnD],[Etc] into your temp table
Select [ColumnB],[ColumnC],[ColumnD],[Etc] into your original table.
... aka, spell out the columns explicitly, and omit the Identity column.

How to manipulate the TEXT column of DELETED/INSERTED tables in SQL Server trigger

I have a SQL Server table and I need to code a trigger to fire when there is an update on that table.
There is a Text column in this table. I need to compare the old and new value of that column after the update, from the INSERTED and DELETED tables.
The thing is that I absolutely can't change the type of that column.
Does anyone have found a way to bypass this restriction in a SQL Server trigger ?
Instead of a trigger would it possible for you to amend your update query? Here's an example update that returns the before and after values:
-- Declare a table to hold our sample data.
DECLARE #Example TABLE
(
TextField VARCHAR(255)
)
;
-- Populate it.
INSERT INTO #Example
(
TextField
)
VALUES
('a'),
('b'),
('c')
;
-- Update the text field and view the change
UPDATE
#Example
SET
TextField = 'z'
OUTPUT
deleted.TextField AS Old_TextField,
inserted.TextField AS New_TextField
;
You could also use the INTO clause to capture this output into a new table.
For more on the INSERTED and DELETED tables see MSDN.
I decided to do something else, I don't really like it, but it allows me to use a varchar column instead of the text column. So I did this :
ALTER TABLE [MyTable]
ADD [MyVarcharColumn] AS (CONVERT([nvarchar(MAX)],[MyTextColumn]))
With this computed column, I don't need to edit any existing queries or .EDMX (Entity Framework) of an existing project, and my trigger works fine.

How to create a SQL Server table with a column and its values to be generated automatically as a GUID

I need to design a table in SQL Server having some columns, one of these columns (ID column and use sequential uniqueidentifier) should automatically populate its data when inserting other column data.
The values of the ID column should be generated automatically when insertion happens.
Please help me to do this, any help is appreciated.
NB: I am new to this step by step approach will be more helpful
Just create a table with a column ID of datatype uniqueidentifier and set it's default value to newsequentialid():
Then, when you go insert rows into that table, just omit the ID column from the list of columns you're inserted values into:
INSERT INTO dbo.YourTable(ColA, ColB, ....., ColX)
VALUES(.., .. ,. ...)
If you don't explicitly insert a value into ID, the default specification (newsequentialid()) will be used .
As per Marc_s's comment, you should use NEWSEQUENTIALID()
CREATE TABLE myTable (ColumnA uniqueidentifier DEFAULT NEWSEQUENTIALID());
See NEWSEQUENTIALID (Transact-SQL)

How to INSERT INTO Table with SELECT and auto incremented field

I am trying to insert from a table I created into a production table - I was able to do this earlier with a formula that I think caused duplicates and did not populate the primary key(In this case PROSPECT_ID properly. Since it is an auto incremented field and I am using a select from another table to INSERT any help on how to properly auto increment this field in production? MKT_PROSPECT
INSERT INTO MKT_PROSPECT(PROSPECT_ID,RECORD_TYPE,search_name,LABEL_NAME,FIRST_NAME,LAST_NAME,CUSTOMER_CLASS_CODE,CUSTOMER_STATUS_CODE,COMPANY_NAME,JOB_TITLE,FORMATTED_DETAIL,ADDRESS_1,ADDRESS_2,CITY,STATE,POSTAL_CODE,ADDRESS_TYPE_CODE,ADDRESS_STATUS_CODE,HOME_PHONE,EMAIL,ADDOPER)
select PROSPECT_ID,RECORD_TYPE,SEARCH_NAME,LABEL_NAME,FIRST,LAST,CUSTOMER_CLASS_CODE,CUSTOMER_STATUS_CODE,COMPANY,TITLE,FORMATTED_DETAIL,ADDRESS1,ADDRESS2,CITY,STATE,ZIP,ADDRESS_TYPE_CODE,ADDRESS_STATUS_CODE,PHONE,EMAIL,ADDOPER from dbo.prospects
where SEARCH_NAME IS not NULL and LABEL_NAME is not null
If you would like to insert into a table with a specific ID use IDENTITY INSERT ON as John Hartsock said in the comments. It is worth noting that the auto increment column will continue all other inserts (outside of the scope of the Identity Insert) above the largest number.
If you meant to insert and have the table auto generate you just don't include the ID column in the insert:
INSERT INTO MKT_PROSPECT(RECORD_TYPE,search_name,
LABEL_NAME,FIRST_NAME,LAST_NAME,CUSTOMER_CLASS_CODE,
CUSTOMER_STATUS_CODE,COMPANY_NAME,JOB_TITLE,
FORMATTED_DETAIL,ADDRESS_1,
ADDRESS_2,CITY,STATE,POSTAL_CODE,
ADDRESS_TYPE_CODE,ADDRESS_STATUS_CODE,
HOME_PHONE,EMAIL,ADDOPER)
select RECORD_TYPE,SEARCH_NAME,LABEL_NAME,FIRST,LAST,
CUSTOMER_CLASS_CODE,CUSTOMER_STATUS_CODE,COMPANY,TITLE,
FORMATTED_DETAIL,ADDRESS1,ADDRESS2,CITY,STATE,ZIP,
ADDRESS_TYPE_CODE,ADDRESS_STATUS_CODE,
PHONE,EMAIL,ADDOPER from dbo.prospects
where SEARCH_NAME IS not NULL and LABEL_NAME is not null

What is the use of OUTPUT clause in sql server

What is the purpose of the OUTPUT clause? I have gone through the MSDN documentation for the OUTPUT clause, which includes the following example:
DELETE FROM dbo.table1
OUTPUT DELETED.* INTO #MyTableVar
WHERE id = 4 OR id = 2;
From the above query, it seems that deleted records are saved in some magic table called deleted, and the query will load those records into table called MyTableVar from the magic deleted table. .
I still do not understand the purpose of the OUTPUT clause usage.
As another SQL example:
USE AdventureWorks2012;
GO
DECLARE #MyTableVar table( NewScrapReasonID smallint,
Name varchar(50),
ModifiedDate datetime);
INSERT Production.ScrapReason
OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
INTO #MyTableVar
VALUES (N'Operator error', GETDATE());
--Display the result set of the table variable.
SELECT NewScrapReasonID, Name, ModifiedDate FROM #MyTableVar;
--Display the result set of the table.
SELECT ScrapReasonID, Name, ModifiedDate
FROM Production.ScrapReason;
GO
What is this actually doing? Can anyone explain what this clause is doing with an easy example?
UPDATE with non-functioning example:
create proc test
as
CREATE TABLE dbo.table1
(
id INT,
employee VARCHAR(32)
)
go
INSERT INTO dbo.table1 VALUES
(1, 'Fred')
,(2, 'Tom')
,(3, 'Sally')
,(4, 'Alice')
delete from table1
select * from deleted
This gives me an error when I run it, because it can't see the deleted table.
The general purpose of this clause is to capture the changes made to your data without an additional query, which would introduce locking and blocking issues. Example:
DELETE FROM X WHERE Name = 'Foo'
You want to know which IDs were deleted. You can do this naively like this:
SELECT ID FROM X WHERE Name = 'Foo'
DELETE FROM X WHERE Name = 'Foo'
But these selected IDs are unreliable unless you are running in a transaction with isolation level SERIALIZABLE which is usually not the case. Someone else can add, delete or change "Foo"-Records between your two statements. So instead you can use the OUTPUT clause and get back exactly and reliably the deleted IDs without any performance or reliability issues.
Another frequent use is to get the value of inserted default values, especially when using identity columns. For a single insert you can do this:
CREATE TABLE X
(
ID INT IDENTITY,
Name VARCHAR(10)
);
INSERT X (Name) VALUES ('Foo')
SELECT SCOPE_IDENTITY()
But SCOPE_IDENTITY() can give you only the last inserted ID. If you do multiple inserts, like
INSERT X (Name) VALUES ('Foo'), ('Bar')
or
INSERT X (Name) SELECT OtherName FROM Y
and you want to know the inserted IDs, you are out of luck. You can try to find them with another SELECT, but you need another unique column to even formulate the query and then you run into the same issues as with the DELETE sample above. So, the OUTPUT clause lets you identify neatly which Names got which IDs.
You will need these IDs for example when creating dependent records with foreign keys. Think "Order" and "OrderDetails" which are linked by an OrderID column with an IDENTITY clause. Again, with a single INSERT you can get away with using SCOPE_IDENTITY() or ##IDENTITY, but when inserting multiple orders at once, you will need OUTPUT.
When you perform Insert/Update/Delete operation on particular table and want to know what rows are affected OR want to log them for audit trail OR you want to use multiple values of affected rows in subsequent sql statements, you can use OUTPUT clause.
For Insert statement, it will have INSERTED table.
For Delete statement, it will have DELETED table. In case of Update DELETED table will contain rows (with old values) before update operation performed.
For Update statement, it will have DELETED and INSERTED tables.
DELETED table will contain rows (with old values) before update operation performed.
INSERTED table will contain rows (with new values) after update operation performed.
USE AdventureWorks2012;
GO
DECLARE #MyTableVar table( NewScrapReasonID smallint,
Name varchar(50),
ModifiedDate datetime);
INSERT Production.ScrapReason
OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
INTO #MyTableVar
VALUES (N'Operator error', GETDATE());
--Display the result set of the table variable.
SELECT NewScrapReasonID, Name, ModifiedDate FROM #MyTableVar;
--Display the result set of the table.
SELECT ScrapReasonID, Name, ModifiedDate
FROM Production.ScrapReason;
Now your query inserts rows in Production.ScrapReason as well as table variable #MyTableVar. Later it selects inserted rows from Production.ScrapReason and #MyTableVar. Thus you can compare both the resultset and it must have identical rows (considering Production.ScrapReason is empty table.)
I hope it makes sense!
Edit:
Inserted/Deleted tables will be available with Insert/Update/Delete statement and not after that. You may want to store those magic table values in db table or temp table.
Without the OUTPUT clause, how would you know which rows were deleted? Your example seems so simple because you already know the Id values, but what if you did this:
DELETE FROM T WHERE SomeColumn LIKE 'SomePattern%'
And you want to find out what was deleted. That's the purpose of the OUTPUT clause.

Resources