Creating tables and choosing types
Write CREATE TABLE statements: columns, types, NULL rules and a primary key. Plus computed columns, temporary tables and scripts you can safely run twice.
CREATE TABLE names the table and lists its columns, each with a type and a NULL rule. BuildMart is about to start buying from suppliers, so it needs a Suppliers table:
CREATE TABLE dbo.Suppliers ( SupplierId int NOT NULL IDENTITY PRIMARY KEY, Name nvarchar(60) NOT NULL, Phone varchar(20) NULL, CreditLimit decimal(10,2) NOT NULL, Rating tinyint NULL, CreatedAt datetime2(0) NOT NULL); SELECT * FROM dbo.Suppliers;SupplierId Name Phone CreditLimit Rating CreatedAt ---------- ---- ----- ----------- ------ ---------
dbo.Suppliers: always include the schema when you create something.NOT NULL/NULL: whether a value is required. If you leave it out, SQL Server usually assumes NULL is allowed, so say it every time.IDENTITY: SQL Server numbers new rows itself (1, 2, 3, …). It has its own lesson later in this module.PRIMARY KEY: the column that identifies each row. It must be unique and can never be NULL.
Design it yourself
Choosing a type: a checklist
| The data is… | Use | Not |
|---|---|---|
int (or bigint for billions) | float | |
decimal(p, s) | float, money (it rounds oddly in division) | |
nvarchar(n) with a realistic n | nvarchar(max) “just in case” | |
Shipped, GB) | varchar(n) or char(n) | nvarchar(max) |
varchar(n): it is text that happens to contain digits | int (loses leading zeros) | |
date | ||
datetime2(0) (to the second) or datetimeoffset | datetime | |
bit | char(1) with Y and N |
Primary keys: natural or surrogate?
SupplierId. Natural keys sound neat but have a habit of changing (people change email addresses, companies change names) or turning out not to be unique. Most tables use a surrogate int IDENTITY key and add a UNIQUE constraint on the natural value; the Constraints lesson shows how.
Computed columns
CREATE TABLE dbo.QuoteLines ( QuoteLineId int NOT NULL IDENTITY PRIMARY KEY, Product nvarchar(60) NOT NULL, Quantity int NOT NULL, UnitPrice decimal(10,2) NOT NULL, LineTotal AS (Quantity * UnitPrice)); INSERT INTO dbo.QuoteLines (Product, Quantity, UnitPrice)VALUES (N'Cement 25 kg', 20, 7.20), (N'Sand 25 kg', 15, 4.10); SELECT Product, Quantity, UnitPrice, LineTotal FROM dbo.QuoteLines;Product Quantity UnitPrice LineTotal ------------ -------- --------- --------- Cement 25 kg 20 7.20 144.00 Sand 25 kg 15 4.10 61.50
Temporary tables
# is temporary: it lives in tempdb, only your connection can see it, and it disappears when you disconnect. It is handy for holding intermediate results while you work something out.
CREATE TABLE #Basket ( ProductId int NOT NULL, Quantity int NOT NULL); INSERT INTO #Basket (ProductId, Quantity) VALUES (4, 10), (5, 10); SELECT * FROM #Basket;ProductId Quantity
--------- --------
4 10
5 10Scripts you can run twice
CREATE TABLE dbo.Products (ProductId int);Msg 2714, Level 16, State 6, Line 1 There is already an object named 'Products' in the database.
DROP TABLE IF EXISTS removes a table only when it is there, which is how BuildMart’s setup script can be re-run to reset everything. Use it in scripts that build test data; never casually against real data, because the rows go with the table.
DROP TABLE IF EXISTS dbo.Deliveries; CREATE TABLE dbo.Deliveries ( DeliveryId int NOT NULL IDENTITY PRIMARY KEY, OrderId int NOT NULL, DeliveredOn date NULL); SELECT name FROM sys.tables WHERE name = 'Deliveries';name ---------- Deliveries
dbo.Vans for BuildMart’s delivery vans: VanId (a whole-number IDENTITY primary key), Registration (up to 8 characters, required), PayloadKg (a whole number, required) and LastServiced (a date, may be unknown). Then list its columns and NULL rules from INFORMATION_SCHEMA.COLUMNS.
Show a hint
varchar(8) fits. Order the column list by ORDINAL_POSITION.
Show the solution
CREATE TABLE dbo.Vans ( VanId int NOT NULL IDENTITY PRIMARY KEY, Registration varchar(8) NOT NULL, PayloadKg int NOT NULL, LastServiced date NULL); SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLEFROM INFORMATION_SCHEMA.COLUMNSWHERE TABLE_NAME = 'Vans'ORDER BY ORDINAL_POSITION;COLUMN_NAME DATA_TYPE IS_NULLABLE ------------ --------- ----------- VanId int NO Registration varchar NO PayloadKg int NO LastServiced date YES
Remember
CREATE TABLE schema.Name (column type NULL|NOT NULL, …); say NULL or NOT NULL for every column.Choose types by what the data means: ids int, moneydecimal, people’s textnvarchar(n), codesvarchar, datesdate.Every table needs a primary key: unique, never NULL, ideally a short surrogate int IDENTITY.Computed columns ( AS expression) are worked out on read and cannot be written to.#Temptables live only for your connection;DROP TABLE IF EXISTSmakes setup scripts re-runnable.