<style> .reveal-up, .reveal-left, .reveal-right, .reveal-stagger > * { opacity: 1 !important; transform: none !important; } </style>
  1. Learn
  2. SQL
  3. Creating and changing data
All lessons in this course

Lesson 8 of 54 14 minBeginner

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:

Query.sql
INSERT INTO dbo.Categories (CategoryId, Name)VALUES (8, N'Garden'); SELECT * FROM dbo.Categories WHERE CategoryId >= 7;
Output
CategoryId  Name
----------  --------
         7  Plumbing
         8  Garden

Try the statements below, including the ones that fail. Each runs on a fresh BuildMart, and every message is SQL Server’s own:

Interactive

Try some INSERT statements

Each statement runs on a fresh copy of BuildMart.

Statement.sql
INSERT INTO dbo.Categories (CategoryId, Name)VALUES (8, N'Garden'); SELECT * FROM dbo.Categories WHERE CategoryId >= 6;
CategoryIdName
16Safety
27Plumbing
38Garden
The column list says which columns the values go into, in order: 8 goes into CategoryId, Garden into Name.

Columns you leave out

A column missing from the list gets its DEFAULT value if it has one, an IDENTITY number if it is an IDENTITY column, and otherwise NULL. If it is NOT NULL with no default, the whole INSERT fails. Products needs every column except ProductId:

Query.sql
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;
Output
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     90

INSERT … SELECT: copy rows from a query

Instead of VALUES, an INSERT can take the result of a SELECT. Every row the query returns is inserted. Here BuildMart keeps a list of products to reorder:

Query.sql
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;
Output
ProductId  Name              Quantity
---------  ----------------  --------
        2  Cordless drill         100
        9  Wall plugs (100)       100
       12  Safety goggles         100

SELECT … 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.

Query.sql
SELECT ProductId, Name, PriceINTO dbo.PriceBackupFROM dbo.ProductsWHERE CategoryId = 5; SELECT * FROM dbo.PriceBackup;
Output
ProductId  Name                Price
---------  ------------------  -----
       10  Masonry paint 10 L  54.00
       11  Paint roller set    12.50

OUTPUT: see what was inserted

The 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:

Query.sql
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');
Output
ProductId  Name
---------  ------------
       13  Garden spade
       14  Leaf rake
Quick check

Which columns can you leave out of an INSERT?

Quick check

What does SELECT * INTO dbo.Copy FROM dbo.Products; do if dbo.Copy already exists?

Practice

BuildMart opens a garden section. Add category 8, Garden, 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

Two INSERT statements: one into Categories, one into Products with two rows in VALUES. Filter the final SELECT on CategoryId = 8.

Show the solution
Solution.sql
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;
Output
ProductId  Name              Price  Stock  Unit
---------  ----------------  -----  -----  ----
       13  Garden hose 30 m  27.99     18  each
       14  Compost 40 L       5.49     60  bag

Remember

  • 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 … SELECT copies query results into an existing table; SELECT … INTO creates a new one.
  • OUTPUT inserted.* returns the new rows, including generated ids.
0 of 54 lessons completed