You're mixing up casing styles for T-SQL keywords - pick one: ANNOYINGCASE
or readablecase
, but don't use both in the same script. I have no bias or preference whatsoever for either*, all that matters is consistency.
Semicolons are not required to indicate the end of a statement, but they are nonetheless a good habit to have.
You inline primary keys and let the server name them. I might have a fetish for naming things, but I like my PK's named PK_TableName
.
Speaking of naming, the Part
table should be named Parts
, and should probably have a natural key in the form of a unique constraint on the PartNumber
column... which I find is a redundant name - Number
would be better.
Foreign keys have potentially ambiguous names, or will be when your schema grows. I like naming my FK's FK_ReferencedTable_AlteredTable[_ColumnName]
, where the [_ColumnName]
part is only needed for when there are multiple FK's on the same table referencing the same table, like when an OrderHeaders
table references a FiscalCalendars
table with its OrderDateCalendarId
, ShipDateCalendarId
and CancelDateCalendarId
, which would respectively be FK_FiscalCalendars_OrderHeaders_OrderDate
, FK_FiscalCalendars_OrderHeaders_ShipDate
and FK_FiscalCalendars_OrderHeaders_CancelDate
. So in your case that would be FK_Parts_BillOfMaterials
and FK_BillOfMaterials_BillOfMaterials
. Being rigorously consistent about naming foreign keys makes it easy to instantly know what tables are involved and in which direction, just by looking at the FK's name. Oh, and I agree with @RubberDuck - use BillOfMaterials
, and keep bom
for table aliases when querying the schema.
You're not specifying the schema you're creating the tables in. Better be explicit; you're not specifying the seed for your IDENTITY
columns - again, better be explicit.
I hate to see Description
be syntax-highlighted in SSMS - I like that you're avoiding that by enclosing the name in square brackets. But then, the issue could be avoided altogether by calling the column Name
instead - that way you don't have to use square brackets everywhere, and Description
doesn't stick out like a sore thumb by being the only name using square brackets.
That said, NVARCHAR(MAX)
has implications that make it an annoying field, especially if the longest description/name is going to be 200, or even 1024 characters. Don't use MAX
for anything below 4000 characters.
Also, I think you're abusing NULL
columns. Does a part that has no number, no description and no price really make sense? Wouldn't that rather be an empty number, an empty description and a 0 price?
Comma-first style makes it easier to change the order of the columns if you ever want to do that.
Lastly, and again this might be just me, but I like when I can run a T-SQL script twice in a row without it blowing up or doing weird things.
Putting it all together (making a few assumptions):
use [database_name]; -- trust me, this one is a life saver
go;
/* drop FK constraints */
if exists (select * from sys.foreign_keys where name = 'FK_BillOfMaterials_BillOfMaterials')
alter table BillOfMaterials drop constraint FK_BillOfMaterials_BillOfMaterials;
if exists (select * from sys.foreign_keys where name = 'FK_Parts_BillOfMaterials')
alter table BillOfMaterials drop constraint FK_Parts_BillOfMaterials;
/* drop tables */
if exists (select * from sys.tables where name = 'Parts')
drop table Parts;
if exists (select * from sys.tables where name = 'BillOfMaterials')
drop table BillOfMaterials;
/* create tables */
create table dbo.Parts (
Id int identity(1,1) not null
,Number nvarchar(50) not null
,Name nvarchar(250) not null
,ListPrice decimal(12,2) not null -- 2 decimals might be a little short in some cases
,constraint PK_Parts primary key clustered (Id)
,constraint NK_Parts unique (Number) -- "NK" == "Natural Key" (assumption here)
);
create table dbo.BillOfMaterials (
Id int identity(1,1) not null
,PartId int not null
,ParentId int null
,Quantity int not null
,constraint PK_BillOfMaterials primary key clustered (Id)
);
/* add FK constraints */
alter table dbo.BillOfMaterials add constraint FK_BillOfMaterials_BillOfMaterials
foreign key (ParentId) references dbo.BillOfMaterials (Id);
alter table dbo.BillOfMaterials add constraint FK_Parts_BillOfMaterials
foreign key (PartId) references dbo.Parts (Id);
*cough
[Description]
column? \$\endgroup\$