Sql Server create table queries - sql

I am using Sql Server Migration assistant to migrate my DB from MySql to SQL Server and in the process learning Sql Server.
The following is the create table syntax for the autogenerated schema.
CREATE TABLE [dbo].[TABLE1] (
[COLUMN1] BIGINT IDENTITY (131556, 1) NOT NULL,
[COLUMN2] INT CONSTRAINT [DF__TABLE_1__PRD_I__24E777C3] DEFAULT ((0)) NULL,
[COLUMN3] INT CONSTRAINT [DF__TABLE1__PROMO__2AA05119] DEFAULT ((0)) NULL,
CONSTRAINT [PK_TABLE1] PRIMARY KEY CLUSTERED ([COLUMN1] ASC)
);
GO
CREATE NONCLUSTERED INDEX [COLUMN3]
ON [dbo].[TABLE1]([COLUMN3] ASC);
GO
EXECUTE sp_addextendedproperty #name = N'MS_SSMA_SOURCE', #value = N'TABLE1',
#level0type = N'SCHEMA', #level0name = N'dbo', #level1type = N'TABLE',
#level1name = N'TABLE1';
I am trying to understand and cleanup the schema.Can someone please help with the following (naive) questions?
Why should the primary key (COLUMN1) specified as a PRIMARY KEY CLUSTERED?
In the original MySql table, COLUMN3 indexed. Is NONCLUSTERED INDEX the equivalent for Sql Server? What is the meaning of
CREATE NONCLUSTERED INDEX [COLUMN3]
ON [dbo].[TABLE1]([COLUMN3] ASC);
I did not understand the following:
EXECUTE sp_addextendedproperty #name = N'MS_SSMA_SOURCE', #value = N'TABLE1',
#level0type = N'SCHEMA', #level0name = N'dbo', #level1type = N'TABLE',
#level1name = N'TABLE1';
Can someone explain what it does?
Is the above create table syntax the minimal syntax to achieve what it does?
I have 131555 rows in my MySql table. Should I be specifying IDENTITY (131556, 1) to start auto increment of key from 131556 after I migrate data?

1.Why should the primary key (COLUMN1) specified as a "PRIMARY KEY CLUSTERED"?
It is generally best for every SQL Server table to have a clustered index, and only one clustered index is allowed per table because the b-tree leaf nodes of the clustered index are the actual data pages. The index supporting the primary key is often the best candidate but you can make the PK non-clustered and have different index as the clustered one if that's advantageous for your particular situation. For example, if your queries of most often range searches on COLUMN3 instead of queries that select or join by COLUMN1, the COLUMN3 index might be a better choice along with a NONCLUSTERED primary key.
2.In the original MySql table, COLUMN3 indexed. Is NONCLUSTERED INDEX the equivalent for Sql Server? What is the meaning of
A non-clustered index is also a b-tree index, allowing rows to be located by the index key more efficiently than a table scan.
3.I did not understand the following:
EXECUTE sp_addextendedproperty #name = N'MS_SSMA_SOURCE', #value =
N'TABLE1', #level0type = N'SCHEMA', #level0name = N'dbo', #level1type
= N'TABLE', #level1name = N'TABLE1';
Can someone explain what it does?
SQL Server has an extended property feature that allows you to attach meta-data to database objects. In this case, SSMA added an extended property to indicate the table was created by the tool.
4.Is the above create table syntax the minimal syntax to achieve what it does?
No. For example, one could omit the constraint names and SQL Server would generate a name automatically. However, the best practice is to explicitly name constraints to facilitate subsequent DDL changes and so that the purpose is self-documenting. Personally, I'd name the default constraints like DF_TABLENAME_COLUMNNAME.
5.I have 131555 rows in my MySql table. Should I be specifying IDENTITY (131556, 1) to start auto increment of key from 131556 after
I migrate data?
If you were to create the table with IDENTITY(1,1) and then insert rows with the IDENTITY INSERT ON option, SQL Server will automatically adjust the next IDENTITY according to the highest value inserted. I don't know much about SSMA but it looks like SSMA already did that for you.

1 and 2. You should probably read this description of the differences between a clustered and non-clustered index: http://msdn.microsoft.com/en-au/library/ms190457.aspx. In short there can be only one clustered index on a table and it defines the sort order for data in the table. You can have many non-clustered indexes on a table.
SQL Server allows you to add extended properties to objects - see here for details: http://technet.microsoft.com/en-us/library/ms190243%28v=sql.105%29.aspx. Basically they are for storing metadata about the object - a description for the table for example, or an input mask for a column.
Here's the full syntax for creating tables: http://msdn.microsoft.com/en-AU/library/ms174979.aspx. I note that your example is creating the table and adding some default constraints. You could rewrite this as
CREATE TABLE [dbo].[TABLE1]
(
[COLUMN1] BIGINT IDENTITY (131556, 1) NOT NULL,
[COLUMN2] INT DEFAULT ((0)) NULL,
[COLUMN3] INT NULL DEFAULT (0),
CONSTRAINT [PK_TABLE1] PRIMARY KEY CLUSTERED ([COLUMN1] ASC)
);
It really depends on whether you want to retain your existing key values, which I would assume you do. If so you should insert the data with
SET IDENTITY_INSERT yourTable ON
Read about identity columns here: http://msdn.microsoft.com/en-us/library/ms186775.aspx

Related

How to force Microsoft Database Project generate ALTER statement for primary key constraint instead of creating temp table?

I have following script for LoginLogo table:
CREATE TABLE [LoginLogo] (
[LoginLogoId] INT IDENTITY (1, 1) NOT NULL,
[LoginId] INT NOT NULL,
[LogoNm] NVARCHAR(255) NULL,
CONSTRAINT [PK_LoginLogo_LoginLogoId] PRIMARY KEY CLUSTERED ([LoginId] ASC),
CONSTRAINT [FK_LoginLogo_LoginId] FOREIGN KEY ([LoginId])
REFERENCES [Login] ([LoginId])
);
GO
CREATE NONCLUSTERED INDEX [IF_LoginLogo_LoginId]
ON [LoginLogo]([LoginId] ASC)
ON [INDX];
I need to change Primary Key Constraint, so I've just changed one line, please see below the change:
CONSTRAINT [PK_LoginLogo_LoginLogoId] PRIMARY KEY CLUSTERED ([LoginLogoId] ASC),
Database project perfectly build changed code, but when it generates database update statement it generates temp table instead of simple ALTER statement. See below generated script:
CREATE TABLE [tmp_ms_xx_LoginLogo] (
[LoginLogoId] INT IDENTITY (1, 1) NOT NULL,
[LoginId] INT NOT NULL,
[LogoNm] NVARCHAR (255) NULL,
CONSTRAINT [tmp_ms_xx_constraint_PK_LoginLogo_LoginLogoId1]
PRIMARY KEY CLUSTERED ([LoginLogoId] ASC)
);
IF EXISTS (SELECT TOP 1 1
FROM [apps].[LoginLogo])
BEGIN
SET IDENTITY_INSERT [apps].[tmp_ms_xx_LoginLogo] ON;
INSERT INTO [apps].[tmp_ms_xx_LoginLogo] ([LoginLogoId], [LoginId], [LogoNm])
SELECT [LoginLogoId],
[LoginId],
[LogoNm],
FROM [LoginLogo]
ORDER BY [LoginLogoId] ASC;
SET IDENTITY_INSERT [tmp_ms_xx_LoginLogo] OFF;
END
DROP TABLE [LoginLogo];
EXECUTE sp_rename N'[tmp_ms_xx_LoginLogo]', N'LoginLogo';
EXECUTE sp_rename N'[tmp_ms_xx_constraint_PK_LoginLogo_LoginLogoId1]',
N'PK_LoginLogo_LoginLogoId', N'OBJECT';
Is it possible to tell Database project to generate ALTER statement instead of creating temp table? How can I force Microsoft Database Project to do that?
Bearing in mind that if you change the clustered index of a table, the table will be rebuilt regardless of whether the script does ALTER TABLE or the SSDT-generated stuff with temp tables, the usual way to solve these problems is to do the ALTER ahead of time
Meaning, you need a script, often referred to as a pre-pre-deploy script (pre-deploy won't work, as it is run post-comparison) that makes the expensive change, so that when the comparison is run the change has already occurred, and hence doesn't get repeated by the dacpac deployment.
This script needs to be run as part of your deployment, before you do any of the sqlpackage stuff. You can specify the change as alter table in this script.
In this particular instance, where the table is going to be rebuilt either way, I can't see it making a great deal of difference to the overall deployment time.

Microsoft SQL - Cannot delete a table, "preparing update script" forever

I am using Visual Studio 2015 and have a data connection to an SQL Database on Azure. I can update things just fine but now I need to delete an entire table altogether and it is stuck at "Preparing update script..." forever. How do I remove the table? It does not have any relations with other tables or anything.
Can you please use SQL Server Management Studio for that? Sometimes, i have the same problem with the VS Explorer, and changing to the SSMS almost always is the solution.
If your SQL Azure is not V12 yet, you can do it from the SQL Azure Silverlight portal (clicking on the Manage button on the SQL Azure dasbhoard), but it is not very viable solution.
If that is the helpful answer, please mark it as a helpful or as the answer. Thanks!
This happens when there is a conflict in your database. (I don't have any article reference/s, this is just from my own experience)
For example, you have a stored procedure like this:
INSERT INTO dbo.Employee_Image
(user_image,
file_extension,
employee_id
)
VALUES
(#user_image,
#file_extension,
#FK_Employee_Image_To_Employee_Table
)
And a table like this:
CREATE TABLE [dbo].[Employee_Image] (
[user_image_id] INT IDENTITY (1, 1) NOT NULL,
[employee_id] INT NULL,
[user_image] VARBINARY (MAX) NULL,
[file_extension] VARCHAR (12) NULL,
PRIMARY KEY CLUSTERED ([user_image_id] ASC),
CONSTRAINT [AK_Employee_Image_employee_id] UNIQUE NONCLUSTERED ([employee_id] ASC),
CONSTRAINT [FK_Employee_Image_To_Employee_Table] FOREIGN KEY ([employee_id]) REFERENCES [dbo].[Employee] ([employee_id])
);
If you remove some of the columns (e.g. the file_extension) like this (and try to update):
CREATE TABLE [dbo].[Employee_Image] (
[user_image_id] INT IDENTITY (1, 1) NOT NULL,
[employee_id] INT NULL,
[user_image] VARBINARY (MAX) NULL,
PRIMARY KEY CLUSTERED ([user_image_id] ASC),
CONSTRAINT [AK_Employee_Image_employee_id] UNIQUE NONCLUSTERED ([employee_id] ASC),
CONSTRAINT [FK_Employee_Image_To_Employee_Table] FOREIGN KEY ([employee_id]) REFERENCES [dbo].[Employee] ([employee_id])
);
The "Preparing Update Script" is going to load like FOREVER. But if you also remove the file_extension column in your stored procedure like this (then the "Preparing Update Script" is going to complete fast):
INSERT INTO dbo.Employee_Image
(user_image,
employee_id
)
VALUES
(#user_image,
#FK_Employee_Image_To_Employee_Table
)

Clustered index trouble

In our production system (SQL Server 2008 / R2) there is a table in which generated documents are stored.
The documents have a reference (varchar) and a sequence_nr (int). The document may be generated multiple times and each iteration gets saved in this table incrementing the sequence number. Additionally each record has a data column (varbinary) and a timestamp as well as a user tag.
The only reason to query this table is for auditing purposes later on and during inserts.
The primary key for the table is clustered over the reference and sequence_nr columns.
As you can probably guess generation of documents and thus the data in the table (since a document can be generated again at a later time) does not grow in order.
I realized this after inserts in the table started timing out.
The inserts are performed with a stored procedure. The stored procedure determines the current max sequence_nr for the given reference and inserts the new row with the next sequence_nr.
I am fairly sure a poor choice of clustered index is causing the timeout problems, since records will be inserted for already existing references, only with a different sequence_nr and thus may end up anywhere in the record collection, but most likely not at the end.
On to my question: would it be better to go for a non-clustered index as primary key or would it be better to introduce an identity column, make it a clustered primary key and keep an index for the combination of reference and sequence_nr?
Knowing that for the time being (and not at all as far as we can foresee) there is no need to query this table intensively, except for the case where a new sequence_nr must be determined.
Edit in answer to questions:
Tbh, I'm not sure about the timeout in the production environment. I do know that new documents get added in parallel running processes.
Table:
CREATE TABLE [dbo].[tbl_document] (
[reference] VARCHAR(50) NOT NULL,
[sequence_nr] INT NOT NULL,
[creation_date] DATETIME2 NOT NULL,
[creation_user] NVARCHAR (50) NOT NULL,
[document_data] VARBINARY(MAX) NOT NULL
);
Primary Key:
ALTER TABLE [dbo].[tbl_document]
ADD CONSTRAINT [PK_tbl_document] PRIMARY KEY CLUSTERED ([reference] ASC, [sequence_nr] ASC)
WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF);
Stored procedure:
CREATE PROCEDURE [dbo].[usp_save_document] #reference NVARCHAR (50),
#sequence_nr INT OUTPUT,
#creation_date DATETIME2,
#creation_user NVARCHAR(50),
#document_data VARBINARY(max)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #current_sequence_nr INT
SELECT #current_sequence_nr = max(sequence_nr)
FROM [dbo].[tbl_document]
WHERE [reference] = #reference
IF #current_sequence_nr IS NULL
BEGIN
SELECT #sequence_nr = 1
END
ELSE
BEGIN
SELECT #sequence_nr = #current_sequence_nr + 1
END
INSERT INTO [dbo].[tbl_document]
([reference],
[sequence_nr],
[creation_date],
[creation_user],
[document_data])
VALUES (#reference,
#sequence_nr,
#creation_date,
#creation_user,
#document_data)
END
Hope that helps.
I would go for the setting the PK not clustered, since:
keeping a b-tree balanced when the key has varchar makes the each leaf much bigger.
you for what you say, you aren't scanning this table for many rows at a time
Since a clustered index physically reorders the records of the table to match the index order, it is only useful if you want to read out several consecutive records in that order because then the whole records can be read by doing a sequential read on the disk.
If you are only using data that is present in the index, there is no gain in make it clustered, because the index in itself (clustered or not) is kept separate from the data and in order.
So for your specific case a non-clustered index is the right way to go. Inserts won't need to reorder the data (only the index) and finding a new sequence_nr can be fulfill by looking at the index alone.

SQL Server 2008 Script to Drop PK Constraint that has a System Generated Name

I am trying to add a clustered index to an existing table in SQL Server 2008, and it needs to be an automated script, because this table exists on several databases across several servers.
In order to add a clustered index I need to remove the PK constraint on the table, and then re-add it as unclustered. The problem is the name of the PK constraint is auto-generated, and there is a guid appended to the end, so it's like "PK_[Table]_D9F9203400."
The name is different across all databases, and I'm not sure how to write an automated script that drops a PK constraint on a table in which I don't know the name of the constraint. Any help is appreciated!
UPDATE:
Answer below is what I used. Full script:
Declare #Val varchar(100)
Declare #Cmd varchar(1000)
Set #Val = (
select name
from sysobjects
where xtype = 'PK'
and parent_obj = (object_id('[Schema].[Table]'))
)
Set #Cmd = 'ALTER TABLE [Table] DROP CONSTRAINT ' + #Val
Exec (#Cmd)
GO
ALTER TABLE [Table] ADD CONSTRAINT PK_Table
PRIMARY KEY NONCLUSTERED (TableId)
GO
CREATE UNIQUE CLUSTERED INDEX IX_Table_Column
ON Table (Column)
GO
You can look up the name of the constraint and write a bit of dynamic SQL to handle the drop.
SELECT name
FROM sys.key_constraints
WHERE parent_object_id = object_id('YourSchemaName.YourTableName')
AND type = 'PK';

SQL Azure not recognizing my clustered Index

I get the following error when I try to insert a row into a SQL Azure table.
Tables without a clustered index are not supported in this version of
SQL Server. Please create a clustered index and try again.
My problem is I do have a clustered index on that table. I used SQL Azure MW to generate the Azure SQL Script.
Here's what I'm using:
IF EXISTS (SELECT * FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[tblPasswordReset]') AND type in (N'U'))
DROP TABLE [dbo].[tblPasswordReset]
GO
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
IF NOT EXISTS (SELECT * FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[tblPasswordReset]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[tblPasswordReset](
[PasswordResetID] [int] IDENTITY(1,1) NOT NULL,
[PasswordResetGUID] [uniqueidentifier] NULL,
[MemberID] [int] NULL,
[RequestDate] [datetime] NULL,
CONSTRAINT [PK_tblPasswordReset] PRIMARY KEY CLUSTERED
(
[PasswordResetID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF)
)
END
GO
Why doesn't SQL Azure recognize my clustered Key? Is my script wrong?
Your script only creates the table if it did not exist yet. Perhaps there still is an old version of the table without a clustered index? You can check with:
select * from sys.indexes where object_id = object_id('tblPasswordReset')
If the table exists without the clustered index, you can add one like:
alter table tblPasswordReset add constraint
PK_tblPasswordReset primary key clustered
As far as I can see, your statement does conform to the Azure create table spec.
Be careful if you're using SSIS. I ran into this same problem, myself, but was using SSIS instead of manually inserting the data. By default SSIS will drop and recreate the table, so even though I had it properly defined with a clustered index, my SSIS script failed. On the "Edit Mappings" step in the SSIS wizard you can manually define the table creation script. I just deleted the table gen script there and my import worked.
(I'd leave this as a comment but my post count is too anemic)