Adding rows with INSERT
Add one row or many with INSERT … VALUES, copy rows with INSERT … SELECT, create a table from a query with SELECT INTO, and see the new rows with OUTPUT.
INSERT adds rows to a table. Name the table, list the columns you are filling, and give the values in the same order:
INSERT INTO dbo.Categories (CategoryId, Name)VALUES (8, N'Garden'); SELECT * FROM dbo.Categories WHERE CategoryId >= 7;CategoryId Name
---------- --------
7 Plumbing
8 GardenColumns you leave out
INSERT INTO dbo.Products (Name, CategoryId, Price, Stock, Unit, AddedOn)VALUES (N'Spirit level 600 mm', 1, 15.00, 20, N'each', '2024-07-01'), (N'Mortar mix 20 kg', 2, 6.40, 90, N'bag', '2024-07-01'); SELECT ProductId, Name, Price, Stock FROM dbo.Products WHERE ProductId > 11;ProductId Name Price Stock
--------- ------------------- ----- -----
12 Safety goggles 6.80 0
13 Spirit level 600 mm 15.00 20
14 Mortar mix 20 kg 6.40 90INSERT … SELECT: copy rows from a query
CREATE TABLE dbo.Reorders ( ProductId int NOT NULL PRIMARY KEY, Name nvarchar(60) NOT NULL, Quantity int NOT NULL); INSERT INTO dbo.Reorders (ProductId, Name, Quantity)SELECT ProductId, Name, 100FROM dbo.ProductsWHERE Stock < 20; SELECT * FROM dbo.Reorders;ProductId Name Quantity
--------- ---------------- --------
2 Cordless drill 100
9 Wall plugs (100) 100
12 Safety goggles 100SELECT … INTO: a new table from a query
SELECT … INTO NewTable creates the table and fills it in one go, copying column names and types from the query. It is perfect for a quick backup copy before you change something. It does not copy keys, constraints or indexes.
SELECT ProductId, Name, PriceINTO dbo.PriceBackupFROM dbo.ProductsWHERE CategoryId = 5; SELECT * FROM dbo.PriceBackup;ProductId Name Price
--------- ------------------ -----
10 Masonry paint 10 L 54.00
11 Paint roller set 12.50OUTPUT: see what was inserted
OUTPUT clause returns the rows an INSERT just added, including values SQL Server filled in itself, such as IDENTITY numbers. It goes between the column list and VALUES:
INSERT INTO dbo.Products (Name, CategoryId, Price, Stock, Unit, AddedOn)OUTPUT inserted.ProductId, inserted.NameVALUES (N'Garden spade', 1, 24.00, 15, N'each', '2024-07-01'), (N'Leaf rake', 1, 16.50, 10, N'each', '2024-07-01');ProductId Name
--------- ------------
13 Garden spade
14 Leaf rakeGarden, then add two products in it in one INSERT: a Garden hose 30 m at 27.99 (stock 18, unit each) and Compost 40 L at 5.49 (stock 60, unit bag), both added on 2024-07-01. Finish by listing the Garden products.
Show a hint
Show the solution
INSERT INTO dbo.Categories (CategoryId, Name)VALUES (8, N'Garden'); INSERT INTO dbo.Products (Name, CategoryId, Price, Stock, Unit, AddedOn)VALUES (N'Garden hose 30 m', 8, 27.99, 18, N'each', '2024-07-01'), (N'Compost 40 L', 8, 5.49, 60, N'bag', '2024-07-01'); SELECT ProductId, Name, Price, Stock, UnitFROM dbo.ProductsWHERE CategoryId = 8;ProductId Name Price Stock Unit
--------- ---------------- ----- ----- ----
13 Garden hose 30 m 27.99 18 each
14 Compost 40 L 5.49 60 bagRemember
INSERT INTO table (columns) VALUES (…), (…)adds one or many rows; the value count must match the column count.Always list the columns, so the statement keeps working when the table changes. Left-out columns get their DEFAULT, an IDENTITY number, or NULL; NOT NULL columns without a default must be given. INSERT … SELECTcopies query results into an existing table;SELECT … INTOcreates a new one.OUTPUT inserted.*returns the new rows, including generated ids.