New uniqueidentifier on the go - sql-server

I want to add a column for a table which would become a PRIMARY KEY and be of type uniqueidentifier. I have this, but I wonder if there is a faster (in fewer code lines) way?
ALTER TABLE [table] ADD [id] [uniqueidentifier]
DEFAULT('00000000-0000-0000-0000-000000000000') NOT NULL
GO
UPDATE [table] SET [id] = NEWID()
GO
ALTER TABLE [table] ADD CONSTRAINT [PK_table_id] PRIMARY KEY CLUSTERED
GO

If you want to keep naming your constraints (and you should), I don't think we can reduce it below 2 statements:
create table T (
Col1 varchar(10) not null
)
go
insert into T (Col1)
values ('abc'),('def')
go
ALTER TABLE T ADD [id] [uniqueidentifier] constraint DF_T_id DEFAULT(NEWID()) NOT NULL
GO
ALTER TABLE T ADD constraint PK_T PRIMARY KEY CLUSTERED (id)
go
drop table T
Note, that I've added a name for the default constraint. Also, this ensures that new rows also have id values assigned. As I said in my comment, it's usually preferable to avoid having columns with values generated by NEWID() clustered - it leads to lots of fragmentation. If you want to avoid that, consider NEWSEQUENTIALID().
If you don't care about constraint names, you can do it as a single query:
ALTER TABLE T ADD [id] [uniqueidentifier] DEFAULT(NEWID()) NOT NULL PRIMARY KEY CLUSTERED

Related

ALTER COLUMN datatype to NOT NULL without dropping index and manually recreating it

I have a table with foreign key:
CREATE TABLE [dbo].[MyTable](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ForeignId] [int] NULL)
ALTER TABLE [dbo].[MyTable] WITH CHECK ADD CONSTRAINT [FK_MyTable_OtherTable] FOREIGN KEY([ForeignId])
REFERENCES [dbo].[OtherTable] ([ID])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[ExpedíciaVýrobky] CHECK CONSTRAINT [FK_MyTable_OtherTable]
I would like to alter the ForeignId datatype to NOT NULL:
ALTER TABLE [dbo].[MyTable] ALTER COLUMN ForeignId INT NOT NULL;
This requires to drop the FK contraint and recreate it.
Is it possible to do so without manually scripting ALTER TABLE CHECK ADD CONSTRAINT ... FOREIGN KEY bla bla with all the details?
For example, if somebody edited the ON DELETE meanwhile, I don't wont to override this change.
EDIT:
In ideal world, I would like to have stored procedure SpAlterColumnToNotNULL(tablename, columnname), that would do the dropping and recreating indexes automatically.

SQL Server temporary tables with a key in different sessions

In a stored procedure, I use a temporary table with a primary key.
CREATE TABLE #tmpTable
(
[RowId] [bigint] IDENTITY(1,1) NOT NULL,
[Id] [numeric](10, 0) NOT NULL
)
ALTER TABLE #tmpTable
ADD CONSTRAINT PK_NamePK PRIMARY KEY CLUSTERED (RowId);
The procedure works, but if I run the same procedure in another session I get an error
'PK_NamePK already exists'
How to use keys or indexes on temporary tables so that they are visible only in their scope?
CREATE TABLE #tmpTable
(
[RowId] [bigint] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[Id] [numeric](10, 0) NOT NULL
)
There is no need to add alter table, you can define by table creation. Hope this work, I have never tried to add primary key on temptable before.

How to alter table add column with named default constraint and named foreign key constraint?

I have two existing tables (TableA and TableB) and I need to add a new column to TableA that has a foreign key to TableB and has a default value that is not null... and both these constraints need to be named. How can I do this?
Adding both constraints in one statement wasn't as easy as I thought it would be and there didn't seem to be many examples out there (at least I wasn't able to find any very easily), so I thought I'd share how I did it here and maybe someone can suggest a better way?
ALTER TABLE [table name] ADD
[New Column Name] [Column Type]
CONSTRAINT [constraint name] DEFAULT ([default value]) NOT NULL,
CONSTRAINT [constraint name] FOREIGN KEY ([New Column Name])
REFERENCES [Other Table] ([Foreign ID])
Example:
ALTER TABLE tableA ADD
myNewColumn BIGINT
CONSTRAINT myNamedConstraint_df default (1) NOT NULL,
CONSTRAINT myNamedConstraint_fk FOREIGN KEY (myNewColumn)
REFERENCES tableB (tableBPrimaryKeyID)
Since it's also common to land here from the question how to add a column with a constraint in MySQL, I'll add an answer for that here too:
CREATE TABLE tableA (id BIGINT NOT NULL AUTO_INCREMENT, PRIMARY KEY (id));
CREATE TABLE tableB (id BIGINT NOT NULL AUTO_INCREMENT, PRIMARY KEY (id));
ALTER TABLE tableA ADD
myNewColumn BIGINT DEFAULT 42 NOT NULL,
ADD CONSTRAINT myNamedConstraint_fk FOREIGN KEY (myNewColumn) REFERENCES tableB (id);
I think there is no way to also name the DEFAULT constraint in MySQL as it's done for sql-server in the other answer, correct me if I'm wrong.

Add primary key column in SQL table

I am student of RDBMS.
I have very basic question let say I have one existing Table in SQL server. What will be script to alter table.
Drop Column 'RowId' if exist.
Drop contraint if exist.
Add one new column 'RowId' into table.
Make this column as primary key.
Autoincrement type int.
In SQL Server 2005 or newer, you could use this script:
-- drop PK constraint if it exists
IF EXISTS (SELECT * FROM sys.key_constraints WHERE type = 'PK' AND parent_object_id = OBJECT_ID('dbo.YourTable') AND Name = 'PK_YourTable')
ALTER TABLE dbo.YourTable
DROP CONSTRAINT PK_YourTable
GO
-- drop column if it already exists
IF EXISTS (SELECT * FROM sys.columns WHERE Name = 'RowId' AND object_id = OBJECT_ID('dbo.YourTable'))
ALTER TABLE dbo.YourTable DROP COLUMN RowId
GO
-- add new "RowId" column, make it IDENTITY (= auto-incrementing)
ALTER TABLE dbo.YourTable
ADD RowId INT IDENTITY(1,1)
GO
-- add new primary key constraint on new column
ALTER TABLE dbo.YourTable
ADD CONSTRAINT PK_YourTable
PRIMARY KEY CLUSTERED (RowId)
GO
Of course, this script may still fail, if other tables are referencing this dbo.YourTable using foreign key constraints onto the pre-existing RowId column...
Update: and of course, anywhere I use dbo.YourTable or PK_YourTable, you have to replace those placeholder with the actual table / constraint names from your own database (you didn't mention what they were, in your question.....)
Note: this answer was added before questions update
Add new column (note: you can only have one IDENTITY column per table)
Drop old primary key
Add new primary key
Drop old column if needed
Sample script:
CREATE TABLE whatever (
OldPKColumn uniqueidentifier NOT NULL,
CONSTRAINT PK_whatever PRIMARY KEY (OldPKColumn)
)
ALTER TABLE whatever
ADD RowId int NOT NULL IDENTITY (1,1);
ALTER TABLE whatever
DROP CONSTRAINT PK_whatever;
ALTER TABLE whatever WITH CHECK
ADD CONSTRAINT PK_whatever PRIMARY KEY CLUSTERED (RowId);
ALTER TABLE whatever
DROP COLUMN oldPKcolumn;
And a random thought... are you trying to reset an IDENTITY column?
If so, then use DBCC CHECKIDENT
Just a comment to improve these great answers (can't use comments yet - I'm one reputation point away from that privilege) and as future reference for myself:
A new IDENTITY (autonumber) column can be added and made the primary key in a single statement as well:
ALTER TABLE [TableName] ADD [ColumnName] int IDENTITY PRIMARY KEY;
I prefer not to bother with constraint names when it doesn't help.
You can specify seed (and increment) values between parantheses after the IDENTITY keyword.

Can this be done with Entity Framework 4 ? If not, what can do this?

I'm making a simplistic trivial pursuit game. I'm not sure if (and then how) I can do the following with EF4 :-
I have a table structure as follows.
Table: TrivialPursuitQuestion
=> ID
=> Unique Question
=> AnswerId
=> AnswerType (ie. Geography, Entertainment, etc).
Table: GeographyAnswer
=> ID
=> Place Name
=> LatLong
Table: EntertainmentAnswer:
=> ID
=> Name
=> BordOn
=> DiedOn
=> Nationality .. and other meta data
... etc ..
So when a person asks a unique question ... the stored proc is able to figure out what type of answer it is (ie. AnswerType field) ... and therefore query against the correct table.
EG.
SELECT #AnswerId = AnswerId, #AnswerType = AnswerType
FROM TrivialPursuitQuestions
WHERE UniqueQuestion = #Question
IF #AnswerId > 0 AND #AnswerType > 0 BEGIN
IF #AnswerType = 1
SELECT *
FROM GeographicAnswers
WHERE AnswerId = #AnswerID
IF #AnswerType = 2
SELECT *
FROM EntertainmentAnswer
WHERE AnswerId = #AnswerId
... etc ...
END
Now .. i'm not sure how to do this with EF. First of all, the stored proc can now return MULTIPLE result types .. so i'm not sure if that's really really bad.
So then I thought, maybe the stored procedure should return Multiple Recordsets .. with all but one recordset containing result(s) ... because by design, only one answer type will ever be found...
EG.
-- Same SELECT as above...
IF #AnswerId > 0 BEGIN
SELECT *
FROM GeographicAnswers
WHERE AnswerId = CASE #AnswerId WHEN 1 THEN #AnswerID ELSE 0 END
SELECT *
FROM EntertainmentAnswer
WHERE AnswerId = CASE #AnswerId WHEN 2 THEN #AnswerID ELSE 0 END
... etc ...
END
and this will return 6 (multiple) recordsets ... but only one of these should ever have some data.
Now, if this is a better solution ... is this possible with EF4 and how?
I'm trying to avoid doing TWO round trips to the db AND also having to figure out WHAT to try and retrieve ... i don't want to have to figure it out .. i'm hoping with some smart modelling the system is just smart enough to say 'OH! u this is the right answer'. Sort of like a Answer Factory (ala Factory Pattern) but with Sql Server + EF4.
ANyone have any ideas?
In the EF Designer you could create an entity called Answer and then create entities that derive from answer called GeographyAnswer, EntertainmentAnswer, ... using a discriminator AnswerType in the Answer entity. Add the Question entity. Add the association from question to Answer, mark it 1:1. Let EF generate the DDL for your database.
Now you can do question.Answer to get the Answer for a Question. You can look at the Type of Answer and show the appropriate UI.
Though, this also begs the question, if it's a 1:1 correspondence between question and answer, why not have a single entity QuestionAnswer and derive from that to create QuestionAnswerGeography, QuestionAnswerEntertainment, ... Now you can pick Questions of a specific type easily: dataContext.QuestionAnswers.ofType<QuestionAnswerGeography>() for example.
Here's an Entity Diagram for the case where an answer may be shared by multiple questions:
This model will allow you do a query like this:
var geographyQuestions = objectContext.Answers.OfType<Geography>().SelectMany(answer => answer.Questions);
The DDL generate by this model is:-
-- Creating table 'Answers'
CREATE TABLE [dbo].[Answers] (
[Id] int IDENTITY(1,1) NOT NULL
);
GO
-- Creating table 'Questions'
CREATE TABLE [dbo].[Questions] (
[Id] int IDENTITY(1,1) NOT NULL,
[AnswerId] int NOT NULL,
[QuestionText] nvarchar(max) NOT NULL
);
GO
-- Creating table 'Answers_Geography'
CREATE TABLE [dbo].[Answers_Geography] (
[PlaceName] nvarchar(max) NOT NULL,
[LatLong] nvarchar(max) NOT NULL,
[Id] int NOT NULL
);
GO
-- Creating table 'Answers_Entertainment'
CREATE TABLE [dbo].[Answers_Entertainment] (
[Name] nvarchar(max) NOT NULL,
[BornOn] datetime NULL,
[DiedOn] datetime NULL,
[Id] int NOT NULL
);
GO
-- --------------------------------------------------
-- Creating all PRIMARY KEY constraints
-- --------------------------------------------------
-- Creating primary key on [Id] in table 'Answers'
ALTER TABLE [dbo].[Answers]
ADD CONSTRAINT [PK_Answers]
PRIMARY KEY CLUSTERED ([Id] ASC);
GO
-- Creating primary key on [Id] in table 'Questions'
ALTER TABLE [dbo].[Questions]
ADD CONSTRAINT [PK_Questions]
PRIMARY KEY CLUSTERED ([Id] ASC);
GO
-- Creating primary key on [Id] in table 'Answers_Geography'
ALTER TABLE [dbo].[Answers_Geography]
ADD CONSTRAINT [PK_Answers_Geography]
PRIMARY KEY CLUSTERED ([Id] ASC);
GO
-- Creating primary key on [Id] in table 'Answers_Entertainment'
ALTER TABLE [dbo].[Answers_Entertainment]
ADD CONSTRAINT [PK_Answers_Entertainment]
PRIMARY KEY CLUSTERED ([Id] ASC);
GO
-- --------------------------------------------------
-- Creating all FOREIGN KEY constraints
-- --------------------------------------------------
-- Creating foreign key on [AnswerId] in table 'Questions'
ALTER TABLE [dbo].[Questions]
ADD CONSTRAINT [FK_QuestionAnswer]
FOREIGN KEY ([AnswerId])
REFERENCES [dbo].[Answers]
([Id])
ON DELETE NO ACTION ON UPDATE NO ACTION;
-- Creating non-clustered index for FOREIGN KEY 'FK_QuestionAnswer'
CREATE INDEX [IX_FK_QuestionAnswer]
ON [dbo].[Questions]
([AnswerId]);
GO
-- Creating foreign key on [Id] in table 'Answers_Geography'
ALTER TABLE [dbo].[Answers_Geography]
ADD CONSTRAINT [FK_Geography_inherits_Answer]
FOREIGN KEY ([Id])
REFERENCES [dbo].[Answers]
([Id])
ON DELETE NO ACTION ON UPDATE NO ACTION;
GO
-- Creating foreign key on [Id] in table 'Answers_Entertainment'
ALTER TABLE [dbo].[Answers_Entertainment]
ADD CONSTRAINT [FK_Entertainment_inherits_Answer]
FOREIGN KEY ([Id])
REFERENCES [dbo].[Answers]
([Id])
ON DELETE NO ACTION ON UPDATE NO ACTION;
GO

Resources