unable to drop and create database in sql server - sql

I'm working with SQL Server 2008 and I can't seem to do drop and create a database.
I've tried a few different ways but I always end up failing to drop or trying to "use" before it seems to be created.
My current attempt looks like this.
use master;
GO
IF EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = N'test')
BEGIN
DROP DATABASE [test];
END
GO
CREATE DATABASE [test];
GO
use [test];
GO
The GO were suggested on a MS forum as a way to stop some issues that occur when selecting databases.
With this I currently get the output (with a ore existing database of the same name) of:
Msg 3702, Level 16, State 4, Line 3
Cannot drop database "test" because it is currently in use.
Msg 1801, Level 16, State 3, Line 1
Database 'test' already exists. Choose a different database name.
Msg 2714, Level 16, State 6, Line 2
There is already an object named 'staff_type' in the database.
With the last 2 lines repeated for every table in my database.

We usually get this error If You've opened any query window with connection to this database, so make sure you close all your opened query windows connected to db which you're trying to drop.
Don't use the database which you're trying to drop. use master to drop any user database that is a good practice.
Make sure No other process is attach to the database you're trying to drop.
EXEC sp_who2
--Run kill spid for each process that is using the database to be dropped.
kill <<processid>> -- Kill 57
Use EXEC sp_who2 and check the DBName column, your database name should not appear in the list, if it appears kill the process using kill <<processid>> then try to drop.
Try this code.
use master
GO
IF EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = N'test')
DROP DATABASE [test]
GO
CREATE DATABASE [test]
GO
use [test]
GO

Right-click on the database and select "Delete" (or left-click it and press the 'del' key).
When the 'Delete Object' dialog appears, make sure to checked "Close existing connections" (see below, it's unchecked by default).
Press "OK".

try this:
use master;
GO
ALTER DATABASE test SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
.....
This will rollback any transaction which is running on that database and brings SQL Server database in a single user mode.

ALTER DATABASE test1 SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE test1 SET OFFLINE;
DROP DATABASE test1
Try this inside stored procedure

This will give you all the current connections:
select spid, hostname, [program_name], open_tran, hostprocess, cmd
from master.dbo.sysprocesses
where dbid = db_id('your_database_name')
Then you could use a t-sql cursor to execute kill #spid, where the value for #spid is from the previous query.

If you are getting the above error while using Master. then you need to close SQL Server Management Studio completely and again open it and connect to it and run your above query.....
Hope,it'll works.....

If you're running into this after having programmatically interacted with the database via ADO.NET and SqlConnection, and you're sure you've closed each of your connections after use and there's really nobody else in there, you might be getting tripped up by connection pooling. Try this C# code to clear the pool prior to connecting to master or another database to issue the DROP DATABASE command on your database:
SqlConnection.ClearPool(yourSqlConnectionObject);

You need to close all the query window using this database also you might need to restart the SQL Server completely. This might solve your problem.

If you have SQL files open that have previously queried the DB you are trying to drop, these will prevent drop. As mention above. Closing these resolved issue for me

Along with mr_eclair's answer above, I would like to add:
All Query window must be closed where the currect db is selected.
Another option is make the db in single user mode.>> it will kill all the other users processes
set OFFLINE WITH ROLLBACK IMMEDIATE. it will make the db in offline mode and bring it back
use sp_who2 to know the users using the current db. and killthe required spids

I faced this type of problem when working with Sql Server Management Studio. After many days of googling and experiments, i finally found an issue.
NB: You ought to firstly create a drop and create table script for this table, if not you will not have your table
1-First create only yours tables with theirs coresponding foreign keys.
2-Create a visual diagram with these table (Sql express-Databases-Databasename-DataBase Diagram-Right click on it and select new database diagram)
3-Add the required datatables on diagram and create the relation between these datatables with corresponding foreign keys added during the creation of tables
4-Then saved your Database
In the case that you have forget to add a given field in a datatable, you can easily drop and create your datatables, to do this, follow these steps:
1-Open the Database diagram of the corresponding database
2-delete all the relationships which exist between the old table to which you want to add some field and others tables
3-then delete the corresponding table from diagram(right click on the table , then select delete table from the datatable)
4-Save the diagram (Ctrl +S)
5-go to the table that you want to drop and create
6-Right click on the table and select( Script table as then select drop and create then go to new Query editor windows), this will script your table in new table, at this time you can modify it to your need, exemple with and old and new same table
Old table
USE [DatabaseName]
GO
/****** Object: Table [dbo].[Administrateur] Script Date: 10/11/2016 2:06:04 PM ******/
DROP TABLE [dbo].[Administrateur]
GO
/****** Object: Table [dbo].[Administrateur] Script Date: 10/11/2016 2:06:04 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Administrateur](
[AdministrateurID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NOT NULL,
[Surname] [nvarchar](max) NULL,
[Phone] [nvarchar](max) NOT NULL,
[Username] [nvarchar](max) NOT NULL,
[Password] [nvarchar](max) NOT NULL,
[Sexe] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_Administrateur] PRIMARY KEY CLUSTERED
(
[AdministrateurID] 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
Now the NEW SAME TABLE WITH 3 NEW FIELDS(Email, Image and Salt)
USE [DatabaseName]
GO
/****** Object: Table [dbo].[Administrateur] Script Date: 10/11/2016 2:06:04 PM ******/
DROP TABLE [dbo].[Administrateur]
GO
/****** Object: Table [dbo].[Administrateur] Script Date: 10/11/2016 2:06:04 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Administrateur](
[AdministrateurID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NOT NULL,
[Surname] [nvarchar](max) NULL,
[Phone] [nvarchar](max) NOT NULL,
[Email] [nvarchar](max) NOT NULL,
[Username] [nvarchar](max) NOT NULL,
[Password] [nvarchar](max) NOT NULL,
[Image] [nvarchar](max) NOT NULL,
[Sexe] [nvarchar](max) NOT NULL,
[Salt] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_Administrateur] PRIMARY KEY CLUSTERED
(
[AdministrateurID] 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
Then in the page of the modified Datatable, Press Execute. It will not execute for the first time and will write some errors encountered, but don't care and just press Execute in second time. At this time, it will execute and write the success message at the bottom of the document.Then select the database and click on Refresh (or press F5), he will update your Database's tables in some computer or you will need to restart the program before seing the updates in others computers(I don't know why, so don't ask me to explain).
Go back now to the diagram and dd the updated table and then connect these(this) table(s) to the tables which has any relation with it.
Hope that this will save the time of someones.
I don

I know I´m late to the game. But here is how I do this in one step. This was happening so often I did´t want to do this in many steps so I combined it to one single step.
DECLARE #databaseName VARCHAR(30);
DECLARE #resource_type_to_kill VARCHAR(30);
DECLARE #processIdToKill INT;
SET #databaseName = 'yourDatabaseName'
SET #resource_type_to_kill = 'DATABASE'
DECLARE #TempSession TABLE
(
ProcessIdToKill INT,
DatabaseName VARCHAR(100),
Request_Mode VARCHAR(100),
HostName VARCHAR(100),
LoginTime VARCHAR(100),
LoginName VARCHAR(100),
Status VARCHAR(100),
Reads VARCHAR(100),
Writes VARCHAR(100)
);
INSERT #TempSession
SELECT DISTINCT
session_id,
name,
request_mode,
host_name,
login_time,
login_name,
status,
reads,
writes
FROM sys.dm_exec_sessions
LEFT OUTER JOIN sys.dm_tran_locks ON sys.dm_exec_sessions.session_id = sys.dm_tran_locks.request_session_id
INNER JOIN sys.databases ON sys.dm_tran_locks.resource_database_id = sys.databases.database_id
WHERE resource_type = #resource_type_to_kill
AND name = #databaseName
ORDER BY name
--SELECT * FROM #TempSession --Debugging
SELECT #processIdToKill = ProcessIdToKill FROM #TempSession
--SELECT #processIdToKill --Debugging
--Run kill for the process that is using the database to be dropped.
DECLARE #SQL nvarchar(1000)
SET #SQL = 'KILL ' + CAST(#processIdToKill as varchar(4))
PRINT 'Killing the process'
EXEC (#SQL)
--And then drop the database
DECLARE #DropSQL nvarchar(1000)
SET #DropSQL = 'DROP DATABASE ' + #databaseName
PRINT 'Dropping the database'
EXEC (#DropSQL)
If there are many processes that are using the database you´ll just have to run this multiple times.

Totally random thought here. But if you have a SQL DB project open in Visual Studio, its open-ness will occupy processes even if you aren't taking any actions or have open query windows in SSMS.
This was the issue in my case. Closing Visual Studio completely, allowed me to drop the database with no issue.

For linux try restarting mssql.server
sudo systctl mssql-server.service
then
DROP Databse "DatabseName"

Related

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"

Cannot insert explicit value because IDENTITY_INSERT is OFF, but cannot SET IDENTITY_INSERT to ON because it is already ON

I have a table in database Foo named Bar, that has a column named ID, which is the primary key, and this database is living on the development SQL Server.
I'm trying to copy data from our production server into the development server so I can play with said data, so I execute the following:
set IDENTITY_INSERT Foo.dbo.Bar ON
insert into Foo.dbo.Bar
(
ID
,Something
,Else
,Is
,Going
,Horribly
,Wrong
,With
,SQL
)
select
ID
,Something
,Else
,Is
,Going
,Horribly
,Wrong
,With
,SQL
from Production.Foo.dbo.Bar
set IDENTITY_INSERT Foo.dbo.Bar OFF
And I get the error
Msg 8107, Level 16, State 1, Line 1
IDENTITY_INSERT is already ON for table 'Foo.dbo.Bar'. Cannot perform SET operation for table 'Foo.dbo.Bar'.
Hmm..okay, so IDENTITY_INSERT is turned on for the table. So I removed the SET IDENTITY_INSERT Foo.dbo.Bar ON from the top of my query, and then execute it, and I get this error:
Msg 544, Level 16, State 1, Line 1
Cannot insert explicit value for identity column in table 'Bar' when IDENTITY_INSERT is set to OFF.
I can execute SET IDENTITY_INSERT Foo.dbo.Bar OFF all day long, but if I try to turn it ON, then SQL Server 2012 says that IDENTITY_INSERT is already turned on.
Funny - i just had the exact same problem with 3 of 4 tables in my brand new ss2012 database.
So i rewrote the table create script to bracket my inserts with 'set identity on' and 'set identity off' and it works. It seems like ss only wants to handle one table's identity at a time ie you cant set a new table identity on until all the others have been turned off.
something like this:
create table Employers
(
id int PRIMARY KEY IDENTITY ,
companyid nvarchar(50) not null,
companyName nvarchar(80) not null,
address nvarchar(80),
Phone nvarchar(10),
);
SET IDENTITY_INSERT employers ON;
insert into Employers(id,companyid,companyName,address,Phone)
Values
(...),
(...)
SET IDENTITY_INSERT employers OFF;
create table customers
(
...
I actually found a different solution to this. This is actually different from Msg 8101, specific to table identity being not set to ON.
To resolve the problem, you need to drop the schema and tables of the same names in the master database.
I have a template script that creates a database and tables and inserts data into those tables, something like:
USE master
GO
CREATE DATABASE [mydb] ON PRIMARY
( NAME = N'mydb', FILENAME = N'C:\SQLDATA\mydb.mdf' , SIZE = 5072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'mydb_log', FILENAME = N'C:\SQLDATA\mydb_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
COLLATE SQL_Latin1_General_CP1_CI_AS
GO
USE [mydb]
GO
CREATE SCHEMA [myschema] AUTHORIZATION [dbo]
GO
CREATE TABLE [myschema].[mytable](
[ID] [int] IDENTITY(1,1) NOT NULL,
[SOMETHING] [int] 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, FILLFACTOR = 90)
)
GO
SET IDENTITY_INSERT [myschema].[mytable] ON
GO
INSERT [myschema].[mytable] ([ID], [SOMETHING]) VALUES (1,2)
GO
SET IDENTITY_INSERT [myschema].[mytable] OFF
GO
The problem was that during the database creation, the statement failed due to the "device activation" error (permissions to the folder where the MDF file will be created), or because of the database file size. The script continued but created the schemas and tables in the master database instead. After I realised the error, I stopped the script and attempted to run it again with the create issues fixed.
Then I got the error.
Msg 8107, Level 16, State 1, Line 2
IDENTITY_INSERT is already ON for table 'master.myschema.mytable'. Cannot perform SET operation for table 'myschema.mytable'.
Msg 544, Level 16, State 1, Line 2
Cannot insert explicit value for identity column in table 'mytable' when IDENTITY_INSERT is set to OFF.
I'm no SQL Server expert, but I think it looks up the schema in the master database first, and because this schema is found and in the current session IDENTITY is already on, it produces this error message.
After dropping the schemas and tables incorrectly created in the master database, my script ran successfully.
I had the exact same error. I was using linq-to-sql and the table and dbml file was initially generated without an identity column on the primary key.
I later updated the primary key to an Identity column but forgot to update the dbml file.
Cannot insert explicit value for identity column in table 'BLAH' when IDENTITY_INSERT is set to OFF
The fix was to update the dbml file funnily enough...

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)

Script table as CREATE includes recent column additions as ALTERs?

I'm running SQL Server Management Studio 2008 against a SQL Server 2005 back-end. SSMS just exhibited a behavior I have never seen before. I don't know if this is something new in SSMS 2008 or just a function of something else.
Basically, what happened in that I added some new columns to an existing table. After adding those columns, I executed "Script table as...CREATE" within the IDE on the table. I expected to just get a single CREATE TABLE statement with all the rows, prvious and new. However, the generated code was the CREATE statement for the original definition of the table, plus individual ALTER TABLE T ADD [Column]... statements for each of the new columns.
This isn't a problem (and actually could be useful from a recent change management point-of-view ... sorta), but it is behavior I've never seen before.
I thought that this may have to do with row length, but the length comes in under the 8,000 byte limit before the table page gets split (forgive my terminology ... I'm a developer and not a DBA). Granted, it's not a small table (127 columns now with the additions and a little over 7,000 byte rowlength).
What am I seeing? Is this a feature/function of SSMS or SQL Server itself? Is this a side effect of the large table definition?
The following sample does not repeat the behavior, but it illustrates (simplified) what I'm seeing:
CREATE TABLE dbo.Table_1
(
ID int NOT NULL,
title nvarchar(50) NOT NULL
)
Then,
ALTER TABLE dbo.Table_1 ADD
[description] [varchar](50) NULL,
[numthing] [nchar](10) NULL
I expected to have this generated:
CREATE TABLE [dbo].[Table_1](
[ID] [int] NOT NULL,
[title] [nvarchar](50) NOT NULL,
[description] [varchar](50) NULL,
[numthing] [nchar](10) NULL,
However, this was generated:
CREATE TABLE [dbo].[Table_1](
[ID] [int] NOT NULL,
[title] [nvarchar](50) NOT NULL)
ALTER TABLE [dbo].[Table_1] ADD [description] [varchar](50) NULL
ALTER TABLE [dbo].[Table_1] ADD [numthing] [nchar](10) NULL
I suspect that you "cleaned up" the SQL in your post since it would normally contain many of other SET and GO statements. I am assuming that you removed the "SET ANSI_PADDING" statements.
Some columns in the table may have ANSI_PADDING set to ON while others are OFF. The ANSI_PADDING option affects all columns created after it was set Since the columns are going to be created in table order, the the ANSI_PADDING option will need to be used a few times depending on the table. The real problem is that MS SQL Server cannot set the ANSI_PADDING option within the CREATE TABLE statement. So it needs to do some of that work after the initial CREATE by using ALTER TABLE statements after the appropriate SET ANSI_PADDING statement.
See: http://kevine323.blogspot.com/2011/03/ansipadding-and-scripting-tables-from.html
I believe you're seeing Microsoft re-using two sections of SQL generation code.
I'm guessing you haven't saved the changes when you click to generate the CREATE script; so the generation code doesn't have an up-to-date version of the table to generate it from. Instead, it runs the normal generation code on the old table, and then the code behind the "Script changes" option to bring it up to date.
Clever code reuse with peculiar results.

Need very simple 'sequence' for GetNextOrderNumber for SQL Server

I'm trying to make an even simpler function than the one described here to get the next value of an order number for a shopping cart.
I don't care if there are gaps
Only completed orders get an ID (i.e. I'm deliberately not using IDENTITY)
Obviously there must not be duplicates
I don't care about performance and locking. If we have so many new orders that I care about lockin then I'll have other problems first
I've found quite a few other similar questions, but not the exact solution i'm looking for.
What I have so far is this :
USE [ShoppingCart]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Sequence_CompletedOrderID]
([val] [int] NOT NULL
CONSTRAINT [DF_Sequence_CompletedOrderID_NextValue] DEFAULT ((520000))
) ON [PRIMARY]
then for the stored proc :
CREATE PROC dbo.GetNextCompletedOrderId
#nextval AS INT OUTPUT
AS
UPDATE dbo.sequence_completedorderid SET #nextval=val += 1;
GO
Like I said I'm trying to base it on the article I linked to above - so perhaps this just a clumsy way of doing it. My SQL isn't quite up to much for even simple things like this, and its past my bedtime. Thanks!
OK, so you already have an IDENTITY column in your main table - but how about just having an additional table with again has an IDENTITY column?? This would save you so much trouble and hassle.....
USE [ShoppingCart]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Sequence_CompletedOrderID]
([val] [int] NOT NULL IDENTITY(520000, 1)
) ON [PRIMARY]
CREATE PROC dbo.GetNextCompletedOrderId
#nextval AS INT OUTPUT
AS
INSERT INTO dbo.Sequence_CompletedOrderID DEFAULT VALUES
SELECT #nextval = SCOPE_IDENTITY()
GO
That way, you can leave all the hassle of making sure things are unique etc. to SQL Server, and it will also make sure you won't ever get back the same value twice from the IDENTITY column!
If you use the Sequence_CompletedOrderID table as a one row table of order IDs then you should use UPDATE and rely on the OUTPUT clause to capture the new value:
CREATE PROC dbo.GetNextCompletedOrderId
#nextval AS INT OUTPUT
AS
SET NOCOUNT ON;
UPDATE dbo.Sequence_CompletedOrderID
SET val=val + 1
OUTPUT #nextval = INSERTED.val;
GO
The solution from #marc_s creates a new row for each number generated. At first I didn't think I liked this, but realized I can use it to my advantage.
What I did was added a date time audit column, and also an #orderid parameter to the stored proc. For a particular orderid it will be guaranteed to return the same completedorderid, which is the number from the sequence generator.
If for some reason my application layer requests the next id, but then crashes before it can commit the transaction - it will still be linked to that order so that when it is requested again the same number will be returned.
This is what I ended up with:
USE [ShoppingCart]
GO
/****** Object: Table [dbo].[Sequence_CompletedOrderID] Script Date: 11/29/2009 03:36:40 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Sequence_CompletedOrderID](
[val] [int] IDENTITY(520000,1) NOT NULL,
[CreateDt] [datetime] NOT NULL CONSTRAINT [DF_Sequence_CompletedOrderID_CreateDt] DEFAULT (getdate()),
[Orderid] [int] NOT NULL CONSTRAINT [DF_Sequence_CompletedOrderID_Orderid] DEFAULT ((0)),
CONSTRAINT [PK_Sequence_CompletedOrderID] PRIMARY KEY CLUSTERED
(
[Orderid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
USE [ShoppingCart]
GO
/****** Object: StoredProcedure [dbo].[GetCompletedOrderId] Script Date: 11/29/2009 03:34:08 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[GetCompletedOrderId]
#orderid AS INT,
#completedorderid AS INT OUTPUT
AS
IF EXISTS (SELECT * FROM dbo.Sequence_CompletedOrderID WHERE orderid = #orderid)
BEGIN
SET #completedorderid =(SELECT val FROM dbo.Sequence_CompletedOrderID WHERE orderid = #orderid)
END
ELSE
BEGIN
INSERT INTO dbo.Sequence_CompletedOrderID (orderid) VALUES (#orderid)
SET #completedorderid =(SELECT SCOPE_IDENTITY())
END
How about using the following statement after inserting data in your table?
UPDATE dbo.sequence_completedorderid
SET #nextval = (SELECT MAX(val) + 1 FROM dbo.sequence_completedorderid)
You don't need a new id column, all you need is to add a new OrderCompleted column (bit), and combine that with the id you already have.
SELECT Id FROM T_Order WHERE OrderCompleted = 1