Create a database schema-script in ssms - sql

I have a fully functional database in sql server. Around 40 tables. I have to install this schema (only the schema, not the data) on multiple other sql server instances. SSMS offers a nice way to auto generate schemas using Tasks --> Generate Scripts. It kinda works, but I am not sure if I understand it correctly:
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TableName]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[TableName](
[id] [uniqueidentifier] NOT NULL,
[history] [varchar](max) NOT NULL,
[isdeleted] [bit] NOT NULL,
CONSTRAINT [PK_RecGroupData] PRIMARY KEY CLUSTERED
(
[rid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[DF_TableName_id]') AND type = 'D')
BEGIN
ALTER TABLE [dbo].[TableName] ADD CONSTRAINT [DF_TableName_id] DEFAULT (newid()) FOR [id]
END
--Just showing one ALTER TABLE and IF NOT EXISTS. The others are generated in the same way.
What happens, if I execute the script, create a new script with the exact same content, but add a new column to it (--> id, history, isdeleted and timestamp)? Does it automatically add the new line? I think yes, of course, but I don't get, how it would know, if the column should be NOT NULL, VARCHAR, BIT, or something similar. It would just execute
ALTER TABLE [dbo].[TableName] ADD CONSTRAINT [DF_TableName_id] DEFAULT (newid()) FOR [id]
(id => new sample column)
But there isn't any information about the data type or any other modifiers.
Also, if I execute my script like this one a second time, it'll throw some errors:
Meldung 1781, Ebene 16, Status 1, Zeile 3
An die Spalte ist bereits ein DEFAULT-Wert gebunden.
Which translates to this:
Message 1781, level 16, status 1, line 3
A DEFAULT value is already bound to the column.
Why does this happen?

The error message is saying that there was a default value assigned to that column before.
Also:
ALTER TABLE [dbo].[TableName] ADD CONSTRAINT [DF_TableName_id] DEFAULT (newid()) FOR [id]
is not the syntax for adding new column - this is to add default value of NEWID() to the column [id].
To add a column you you should follow this steps (with an example inside).
Also how would the SQL Server know the setup settings for the new columns from your manually added lines? It would simply allow you to define them as you want and accept if the syntax is right or through an error if not during the script parse process (can be done by [ctrl] + [F5] in SSMS).

Related

Re-seeding a large sql table

Using version:
Microsoft SQL Server 2008 R2 (SP3-OD) (KB3144114) - 10.50.6542.0 (Intel X86)
Feb 22 2016 18:12:09
Copyright (c) Microsoft Corporation
Standard Edition on Windows NT 5.2 <X86> (Build : )
I have a heavy table (135K rows), that I moved from another DB.
It transferred with the [id] column being a standard int column instead of it being the key & seed column.
When trying to edit that field to become an identity specification, with a seed value, its errors out and gives me this error:
Execution Timeout Expired.
The timeout period elapsed prior to completion of the operation...
I even tried deleting that column, to try recreate it later, but i get the same issue.
Thanks
UPDATE:
Table structure:
CREATE TABLE [dbo].[tblEmailsSent](
[id] [int] IDENTITY(1,1) NOT NULL, -- this is what it should be. currently its just an `[int] NOT NULL`
[Sent] [datetime] NULL,
[SentByUser] [nvarchar](50) NULL,
[ToEmail] [nvarchar](150) NULL,
[StudentID] [int] NULL,
[SubjectLine] [nvarchar](200) NULL,
[MessageContent] [nvarchar](max) NULL,
[ReadStatus] [bit] NULL,
[Folder] [nvarchar](50) NULL,
CONSTRAINT [PK_tblMessages] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
I think that your question is a duplicate of Adding an identity to an existing column. That question above has an answer that should be perfect for your situation. I'll reproduce its essential part here below.
But before that, let's clarify why you see the timeout error.
You are trying to add the IDENTITY property to existing column. And you are using SSMS GUI for it. A simple ALTER COLUMN statement can't do it and even if it could, SSMS generates a script that creates a new table, copies over the data into the new table, drops the old table and renames the new table to the old name. When you do this operation via SSMS GUI it runs its scripts with a predefined timeout of 30 seconds.
Of course, you can change this setting in SSMS and increase the timeout, but there is a much better way.
Simple/lazy way
Use SSMS GUI to change the column definition, but then instead of clicking "Save", click "Generate Change Script" in the table designer.
Then save this script to a file and review the generated T-SQL code that GUI runs behind the scene.
You'll see that it creates a temp table with the required schema, copies data over, re-creates foreign keys and indexes, drops the old table and renames the new table.
The script itself is usually correct, but pay close attention to transactions in it. For some reason SSMS often doesn't use a single transaction for the whole operation, but several transactions. I'd recommend to manually review the script and make sure that there is only one BEGIN TRANSACTION at the top and one COMMIT in the end. You don't want to end up with a half-done operation with, say, a table where all indexes and foreign keys were dropped.
If it is a one-off operation, it could be enough for you. Your table is only 2.4GB, so it may take few minutes, but it should not be hours.
If you run the T-SQL script yourself in SSMS, then by default there is no timeout. You can stop it yourself if it takes too long.
Smart and fast way to do it is described in details in this answer by Justin Grant.
The main idea is to use the ALTER TABLE...SWITCH statement to make the change only touching the metadata without touching each page of the table.
BEGIN TRANSACTION;
-- create a new table with required schema
CREATE TABLE [dbo].[NEW_tblEmailsSent](
[id] [int] IDENTITY(1,1) NOT NULL,
[Sent] [datetime] NULL,
[SentByUser] [nvarchar](50) NULL,
[ToEmail] [nvarchar](150) NULL,
[StudentID] [int] NULL,
[SubjectLine] [nvarchar](200) NULL,
[MessageContent] [nvarchar](max) NULL,
[ReadStatus] [bit] NULL,
[Folder] [nvarchar](50) NULL,
CONSTRAINT [PK_tblEmailsSent] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
-- switch the tables
ALTER TABLE [dbo].[tblEmailsSent] SWITCH TO [dbo].[NEW_tblEmailsSent];
-- drop the original (now empty) table
DROP TABLE [dbo].[tblEmailsSent];
-- rename new table to old table's name
EXEC sp_rename 'NEW_tblEmailsSent','tblEmailsSent';
COMMIT;
After the new table has IDENTITY property you normally should set the current identity value to the maximum of the actual values in your table. If you don't do it, new rows inserted into the table would start from 1.
One way to do it is to run DBCC CHECKIDENT after you switched the tables:
DBCC CHECKIDENT('dbo.tblEmailsSent')
Alternatively, you can specify the new seed in the table definition:
CREATE TABLE [dbo].[NEW_tblEmailsSent](
[id] [int] IDENTITY(<max value of id + 1>, 1) NOT NULL,

Understanding creating simple stored procedures

I'm in the process of learning to create stored procedures in Microsoft SQL Server Management Studio. I need to create a stored procedure that adds a single new record to my table. Also, I need to create two extra output parameters along with the stored procedure (I chose ##error and SCOPE_IDENTITY()).
This is the code I use to create my stored procedure:
use bieren
go
if exists
(select name from sysobjects
where name = 'spBierInsert' and xtype = 'p')
drop procedure spBierInsert
go
create procedure spBierInsert
#Biernr int = 0,
#Naam nvarchar(100) = '',
#BrouwerNr int = 0,
#SoortNr int = 0,
#Alcohol real,
#gelukt nvarchar(10) output,
#id int output
as
begin
declare #fout int
insert into bieren
values (#Biernr, #Naam, #BrouwerNr, #SoortNr, #Alcohol)
set #fout = ##error
print 'Foutnummer:' + cast(#fout as varchar(4))
if #fout > 0
set #gelukt = 'Neen: ' + cast(#fout as varchar(4))
else
set #gelukt = 'Ja'
set #id = SCOPE_IDENTITY()
end
I must be doing something wrong, because the result is the following:
Msg 547, Level 16, State 0, Procedure spBierInsert, Line 92
The INSERT statement conflicted with the FOREIGN KEY constraint
"FK_Bieren_Brouwers". The conflict occurred in database "Bieren", table
"dbo.Brouwers", column 'BrouwerNr'.
The statement has been terminated.
Foutnummer:547
(1 row(s) affected)
What have I done incorrectly?
EDIT 30/12/2015: I have updated this question with new information. I originally just used terms like "exampletable" because I had no idea that the search to the answer to my question would be more involved than a single answer, so I've gone ahead and changed the entire code above (as well as the text for the error), and I've added the script for my table underneath. The point of this question is that I come out with code that works, or, that I at least understand what's wrong with it.
USE [Bieren]
GO
/****** Object: Table [dbo].[Bieren] Script Date: 30/12/2015 0:19:56 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Bieren](
[BierNr] [int] NOT NULL,
[Naam] [nvarchar](100) NULL,
[BrouwerNr] [int] NULL,
[SoortNr] [int] NULL,
[Alcohol] [real] NULL,
CONSTRAINT [PK_Bieren] PRIMARY KEY CLUSTERED
(
[BierNr] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Bieren] WITH CHECK ADD CONSTRAINT [FK_Bieren_Brouwers] FOREIGN KEY([BrouwerNr])
REFERENCES [dbo].[Brouwers] ([BrouwerNr])
GO
ALTER TABLE [dbo].[Bieren] CHECK CONSTRAINT [FK_Bieren_Brouwers]
GO
ALTER TABLE [dbo].[Bieren] WITH CHECK ADD CONSTRAINT [FK_Bieren_Soorten] FOREIGN KEY([SoortNr])
REFERENCES [dbo].[Soorten] ([SoortNr])
GO
ALTER TABLE [dbo].[Bieren] CHECK CONSTRAINT [FK_Bieren_Soorten]
GO
Your procedure is created fine. The problem is that you are inserting a value in column 'BrouwerNr' of table "dbo.Brouwers" which doesn't exist in "SoortNr" column of table "dbo.Soorten". There is foreign set on the table "dbo.Brouwers" named "[FK_Bieren_Soorten]" which is causing this restriction. I suggest you look into this article to know more about foreign keys.
The error is because you are inserting 1600 in #ColumnNr, which is a foreign key of another table and does not have 1600 in it.
You can do the following :
right click on "exampletable" table and select 'Script table as'->'Create to'->'new query editor window'
Now,find "ColumnNr" in it. It will be something like this =>
ALTER TABLE [dbo].[exampleTable] WITH CHECK ADD CONSTRAINT [FK_exampleTable_**OtherTableName**_ColumnNr] FOREIGN KEY([ColumnNr])
REFERENCES [dbo].**[OtherTableName]** ([ColumnNr])
GO
Now open the mentioned table "OtherTableName" in the query and look for the column "ColumnNr". It will not be having value 1600.
Try to insert any value in
#ColumnNr = {//Any value from **OtherTableName**},
which is in table "OtherTableName"

why this insert statement cannot insert values in it's second iteration?

I have this reasonably sized stored procedure that accepts 3 collections two UDTT collection and one CSV collection.
I have passed the following values to test stored procedure. However the problems occurred in one small master table called EmpDesignations with 5 columns. There is a loop I used in the store procedure to insert values to EmpDesignations. The loop is required because the values are extracted from the CSV string. As expected it does iterate 2 times with two sets of values. The first iteration the data was inserted successfully but in the second iteration data was not inserted. I have checked weather the data is empty but those variables #tmpEmpID and #tmp contain data. So cannot figure out the problem
The EmpDesignations table definition is
EmpID PK, FK not null
DesigID PK, FK not null
IsValid int not null
UpdtDT datetime not null containts to getDate()
AuthID int not null  EmpID
here is the snapshot of the table columns and types
In the first iteration the passing values to the insert statement is shown in the watch window
As you can see, ##rowcount is 1 so worked in the first round!
In the following watch shows the passing values to the insert statement, this is in the second iteration:
But the ##rowcount is not 1 therefore the control rollbacks all insertions
Here is a video link of the debugging of the insert statement
here is the video of THE SECOND INSERT statement debugging
Table definition is correct, the number of values passed matches the number of input columns, and the variables are filled with values in both iterations, so what could be the problem???
here is the script that was generated by SQL server for the table EmpDesignations
USE [SMSV100]
GO
/****** Object: Table [dbo].[EmpDesignations] Script Date: 04/12/2014 08:50:23 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[EmpDesignations](
[EmpID] [int] NOT NULL,
[DesigID] [int] NOT NULL,
[IsValid] [int] NOT NULL,
[UpdtDT] [datetime] NOT NULL,
[AuthID] [int] NOT NULL,
CONSTRAINT [PK_EmpDesignations] PRIMARY KEY CLUSTERED
(
[EmpID] ASC,
[DesigID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[EmpDesignations] WITH CHECK ADD CONSTRAINT [FK_EmpDesignations_Designations] FOREIGN KEY([DesigID])
REFERENCES [dbo].[Designations] ([DesigID])
GO
ALTER TABLE [dbo].[EmpDesignations] CHECK CONSTRAINT [FK_EmpDesignations_Designations]
GO
ALTER TABLE [dbo].[EmpDesignations] WITH CHECK ADD CONSTRAINT [FK_EmpDesignations_Employees] FOREIGN KEY([EmpID])
REFERENCES [dbo].[Employees] ([EmpID])
GO
ALTER TABLE [dbo].[EmpDesignations] CHECK CONSTRAINT [FK_EmpDesignations_Employees]
GO
ALTER TABLE [dbo].[EmpDesignations] ADD CONSTRAINT [DF_EmpDesignations_UpdtDT] DEFAULT (getdate()) FOR [UpdtDT]
GO
thanks

SQL Insert Failing - Violation of Primary Key Constraint

I am seeing a very strange issue with a SQL Insert statement, I have a simple table, with an ID and 2 datetimes, see create script below -
CREATE TABLE [dbo].[DATA_POPULATION_LOGS](
[ID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[START] [datetime] NOT NULL,
[FINISH] [datetime] NOT NULL,
CONSTRAINT [PK__DATA_POP__3214EC2705D8E0BE] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
I am now trying to run the following insert script -
INSERT INTO [dbo].[DATA_POPULATION_LOGS]
([START]
,[FINISH])
VALUES
(GETDATE()
,GETDATE())
It is failing with the following error -
Msg 2627, Level 14, State 1, Line 1
Violation of PRIMARY KEY constraint 'PK__DATA_POP__3214EC2705D8E0BE'. Cannot insert duplicate key in object 'dbo.DATA_POPULATION_LOGS'. The duplicate key value is (11).
The duplicate key value in the error message above increases every time the insert is executed, so it seems to know it is an identity column.
What would be causing this issue?!
Thanks in advance.
Simon
EDIT
I have now created a copy of this table and can insert into the new table fine using that script, what could be causing it to fail?
Probably someone issued DBCC CHECKIDENT against the table. When you do this, SQL Server will obey you, and try to generate values starting from the RESEED and incrementing by the increment. It doesn't check first to see if those values already exist (even if there is a PK). Simple repro that generates the same error:
USE tempdb;
GO
CREATE TABLE dbo.floob(ID INT IDENTITY(1,1) PRIMARY KEY);
GO
INSERT dbo.floob DEFAULT VALUES;
GO
DBCC CHECKIDENT('dbo.floob', RESEED, 0);
GO
INSERT dbo.floob DEFAULT VALUES;
GO
DROP TABLE dbo.floob;
To stop this from happening, you could figure out what the max value is now, and then run CHECKIDENT again:
DBCC CHECKIDENT('dbo.tablename', RESEED, <max value + 10 or 20 or something here>);

How can I change primary key on SQL Azure

I am going to change the primary key on SQL Azure. But it throws an error when using Microsoft SQL Server Management Studio to generate the scripts. Because every tables on SQL Azure must contains a primary key. And I can't drop it before create. What can I do if I must change it?
Script generated
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[mytable]') AND name = N'PK_mytable')
ALTER TABLE [dbo].[mytable] DROP CONSTRAINT [PK_mytable]
GO
ALTER TABLE [dbo].[mytable] ADD CONSTRAINT [PK_mytable] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF)
GO
Error message
Msg 40054, Level 16, State 2, Line 3
Tables without a clustered index are not supported in this version of SQL Server. Please create a clustered index and try again.
Msg 3727, Level 16, State 0, Line 3
Could not drop constraint. See previous errors.
The statement has been terminated.
Msg 1779, Level 16, State 0, Line 3
Table 't_event_admin' already has a primary key defined on it.
Msg 1750, Level 16, State 0, Line 3
Could not create constraint. See previous errors.
I ran into this exact problem and contacted the Azure team on the forums. Basically it isn't possible. You'll need to create a new table and transfer the data to it.
What I did was create a transaction and within it do the following:
Renamed the old table to OLD_MyTable.
Create the new table with the correct Primary Key and call it MyTable.
Select the contents from OLD_MyTable
into MyTable.
Drop OLD_MyTable.
You may also need to call sp_rename on any constraints so they don't conflict.
See also: http://social.msdn.microsoft.com/Forums/en/ssdsgetstarted/thread/5cc4b302-fa42-4c62-956a-bbf79dbbd040
upgrade SQL V12 and heaps are supported on it. So you can drop the primary key and recreate it.
I appreciate that this may be late in the day for yourself, but it may help others.
I recently came across this issue and found the least painful solution was to download the database from Azure, restore it locally, update the primary key locally (as the key constraint is a SQL Azure specific issue), and then restore the database back into Azure.
This saved any issues in regards to renaming databases or transferring data between them.
You can try the following scripts. Change it to suit for your table def.
EXECUTE sp_rename N'[PK_MyTable]', N'[PK_MyTable_old]', 'OBJECT'
CREATE TABLE [dbo].[Temp_MyTable](
[id] [int] NOT NULL,
[text] [text] NOT NULL CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED (
[id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON))
INSERT INTO dbo.[Temp_MyTable] (Id, Text)
SELECT Id, Text FROM dbo.MyTable
drop table dbo.MyTable
EXECUTE sp_rename N'Temp_MyTable', N'MyTable', 'OBJECT'
This question is outdated because changing PK is already supported in latest version of SQL Azure. And you don't have to create temporary table.