SQL Server表操作 #

一、表概述 #

1.1 表结构 #

text
SQL Server 表结构
├── 列(Columns)
│   ├── 列名
│   ├── 数据类型
│   └── 约束
├── 约束(Constraints)
│   ├── 主键约束
│   ├── 外键约束
│   ├── 唯一约束
│   ├── 检查约束
│   └── 默认约束
├── 索引(Indexes)
│   ├── 聚集索引
│   └── 非聚集索引
└── 触发器(Triggers)

1.2 命名规范 #

text
表命名规范:
├── 表名
│   ├── 单数名词:user, order
│   ├── 小写+下划线:user_profile
│   └── 或帕斯卡命名:UserProfile
│
├── 列名
│   ├── 小写+下划线:created_at
│   └── 有意义的名称
│
├── 主键
│   └── id 或 表名_id
│
├── 外键
│   └── 关联表名_id
│
├── 索引
│   └── ix_表名_列名
│
└── 约束
    ├── pk_表名:主键
    ├── fk_表名_关联表:外键
    ├── uq_表名_列名:唯一
    ├── ck_表名_列名:检查
    └── df_表名_列名:默认

二、创建表 #

2.1 基本语法 #

sql
CREATE TABLE [schema_name.]table_name
(
    column_name data_type [NULL | NOT NULL]
        [CONSTRAINT constraint_name]
        [DEFAULT default_value]
        [IDENTITY [(seed, increment)]]
        [ROWGUIDCOL]
    [, ...n]
    [, CONSTRAINT table_constraint]
)
[ON { filegroup | "default" }]
[TEXTIMAGE_ON { filegroup | "default" }];

2.2 创建简单表 #

sql
-- 创建简单用户表
CREATE TABLE users (
    id INT IDENTITY(1,1),
    name NVARCHAR(50) NOT NULL,
    email VARCHAR(100),
    age INT,
    created_at DATETIME DEFAULT GETDATE()
);

-- 插入数据测试
INSERT INTO users (name, email, age) 
VALUES ('John', 'john@example.com', 25);

SELECT * FROM users;

2.3 创建完整表 #

sql
-- 创建完整的用户表
CREATE TABLE dbo.users (
    id INT IDENTITY(1,1) NOT NULL,
    username NVARCHAR(50) NOT NULL,
    email VARCHAR(100) NOT NULL,
    password_hash NVARCHAR(255) NOT NULL,
    phone VARCHAR(20),
    age INT,
    status BIT DEFAULT 1,
    created_at DATETIME2 DEFAULT SYSDATETIME(),
    updated_at DATETIME2,
    
    -- 主键约束
    CONSTRAINT pk_users PRIMARY KEY (id),
    
    -- 唯一约束
    CONSTRAINT uq_users_username UNIQUE (username),
    CONSTRAINT uq_users_email UNIQUE (email),
    
    -- 检查约束
    CONSTRAINT ck_users_age CHECK (age >= 0 AND age <= 150),
    CONSTRAINT ck_users_email CHECK (email LIKE '%@%.%')
);

-- 创建索引
CREATE INDEX ix_users_email ON dbo.users(email);
CREATE INDEX ix_users_status ON dbo.users(status);

2.4 使用架构 #

sql
-- 创建架构
CREATE SCHEMA sales;
GO

-- 在架构中创建表
CREATE TABLE sales.orders (
    id INT IDENTITY(1,1) PRIMARY KEY,
    customer_id INT NOT NULL,
    order_date DATE DEFAULT GETDATE(),
    total_amount DECIMAL(10,2),
    status NVARCHAR(20) DEFAULT 'pending'
);

三、约束 #

3.1 主键约束 #

sql
-- 创建表时定义主键
CREATE TABLE products (
    id INT PRIMARY KEY,
    name NVARCHAR(100)
);

-- 命名主键约束
CREATE TABLE products (
    id INT CONSTRAINT pk_products PRIMARY KEY,
    name NVARCHAR(100)
);

-- 复合主键
CREATE TABLE order_items (
    order_id INT,
    product_id INT,
    quantity INT,
    CONSTRAINT pk_order_items PRIMARY KEY (order_id, product_id)
);

-- 添加主键到现有表
ALTER TABLE products
ADD CONSTRAINT pk_products PRIMARY KEY (id);

-- 删除主键
ALTER TABLE products
DROP CONSTRAINT pk_products;

3.2 外键约束 #

sql
-- 创建外键
CREATE TABLE orders (
    id INT PRIMARY KEY,
    customer_id INT,
    order_date DATE,
    
    CONSTRAINT fk_orders_customers 
    FOREIGN KEY (customer_id) 
    REFERENCES customers(id)
);

-- 外键选项
CREATE TABLE order_items (
    id INT PRIMARY KEY,
    order_id INT,
    product_id INT,
    
    CONSTRAINT fk_order_items_orders 
    FOREIGN KEY (order_id) 
    REFERENCES orders(id)
    ON DELETE CASCADE      -- 删除时级联删除
    ON UPDATE CASCADE,     -- 更新时级联更新
    
    CONSTRAINT fk_order_items_products 
    FOREIGN KEY (product_id) 
    REFERENCES products(id)
    ON DELETE NO ACTION    -- 删除时报错
    ON UPDATE NO ACTION
);

-- 添加外键
ALTER TABLE orders
ADD CONSTRAINT fk_orders_customers
FOREIGN KEY (customer_id) REFERENCES customers(id);

-- 删除外键
ALTER TABLE orders
DROP CONSTRAINT fk_orders_customers;

3.3 唯一约束 #

sql
-- 创建唯一约束
CREATE TABLE users (
    id INT PRIMARY KEY,
    username NVARCHAR(50) UNIQUE,
    email VARCHAR(100) CONSTRAINT uq_users_email UNIQUE
);

-- 添加唯一约束
ALTER TABLE users
ADD CONSTRAINT uq_users_phone UNIQUE (phone);

-- 复合唯一约束
ALTER TABLE user_roles
ADD CONSTRAINT uq_user_roles UNIQUE (user_id, role_id);

-- 删除唯一约束
ALTER TABLE users
DROP CONSTRAINT uq_users_email;

3.4 检查约束 #

sql
-- 创建检查约束
CREATE TABLE products (
    id INT PRIMARY KEY,
    name NVARCHAR(100),
    price DECIMAL(10,2),
    stock INT,
    
    CONSTRAINT ck_products_price CHECK (price > 0),
    CONSTRAINT ck_products_stock CHECK (stock >= 0)
);

-- 复杂检查约束
CREATE TABLE employees (
    id INT PRIMARY KEY,
    name NVARCHAR(50),
    birth_date DATE,
    hire_date DATE,
    
    CONSTRAINT ck_employees_dates 
    CHECK (hire_date > birth_date AND hire_date <= GETDATE())
);

-- 添加检查约束
ALTER TABLE products
ADD CONSTRAINT ck_products_status 
CHECK (status IN ('active', 'inactive', 'discontinued'));

-- 删除检查约束
ALTER TABLE products
DROP CONSTRAINT ck_products_price;

3.5 默认约束 #

sql
-- 创建默认约束
CREATE TABLE orders (
    id INT PRIMARY KEY,
    status NVARCHAR(20) DEFAULT 'pending',
    created_at DATETIME DEFAULT GETDATE(),
    is_active BIT DEFAULT 1
);

-- 添加默认约束
ALTER TABLE users
ADD CONSTRAINT df_users_status DEFAULT 1 FOR status;

-- 使用函数作为默认值
CREATE TABLE audit_log (
    id INT PRIMARY KEY,
    action NVARCHAR(50),
    action_date DATETIME2 DEFAULT SYSDATETIME(),
    user_name NVARCHAR(100) DEFAULT SUSER_NAME()
);

-- 删除默认约束
ALTER TABLE users
DROP CONSTRAINT df_users_status;

3.6 约束管理 #

sql
-- 查看表约束
SELECT 
    name AS [约束名],
    type_desc AS [类型]
FROM sys.objects
WHERE parent_object_id = OBJECT_ID('users');

-- 使用sp_helpconstraint
EXEC sp_helpconstraint 'users';

-- 禁用约束(外键和检查约束)
ALTER TABLE orders NOCHECK CONSTRAINT fk_orders_customers;

-- 启用约束
ALTER TABLE orders CHECK CONSTRAINT fk_orders_customers;

-- 禁用所有约束
ALTER TABLE orders NOCHECK CONSTRAINT ALL;

-- 启用所有约束
ALTER TABLE orders CHECK CONSTRAINT ALL;

四、修改表 #

4.1 添加列 #

sql
-- 添加单列
ALTER TABLE users ADD phone VARCHAR(20);

-- 添加多列
ALTER TABLE users ADD
    address NVARCHAR(200),
    city NVARCHAR(50),
    country NVARCHAR(50) DEFAULT 'China';

-- 添加带约束的列
ALTER TABLE users ADD
    age INT CONSTRAINT ck_users_age CHECK (age >= 0);

4.2 修改列 #

sql
-- 修改数据类型
ALTER TABLE users ALTER COLUMN name NVARCHAR(100);

-- 修改为NOT NULL
ALTER TABLE users ALTER COLUMN email VARCHAR(100) NOT NULL;

-- 修改列属性
ALTER TABLE users ALTER COLUMN phone VARCHAR(50) NULL;

4.3 删除列 #

sql
-- 删除列
ALTER TABLE users DROP COLUMN phone;

-- 删除有约束的列(需先删除约束)
ALTER TABLE users DROP CONSTRAINT df_users_status;
ALTER TABLE users DROP COLUMN status;

4.4 重命名列 #

sql
-- 使用sp_rename
EXEC sp_rename 'users.name', 'user_name', 'COLUMN';

-- 或者
EXEC sp_rename 
    @objname = 'users.name', 
    @newname = 'user_name', 
    @objtype = 'COLUMN';

4.5 重命名表 #

sql
-- 重命名表
EXEC sp_rename 'users', 'sys_users';

-- 或者
EXEC sp_rename 
    @objname = 'users', 
    @newname = 'sys_users', 
    @objtype = 'OBJECT';

五、删除表 #

5.1 基本删除 #

sql
-- 删除表
DROP TABLE users;

-- 安全删除(SQL Server 2016+)
DROP TABLE IF EXISTS users;

-- 删除多个表
DROP TABLE users, orders, products;

5.2 删除有外键引用的表 #

sql
-- 先删除外键约束
ALTER TABLE orders DROP CONSTRAINT fk_orders_users;

-- 再删除表
DROP TABLE users;

-- 或者使用级联删除(需谨慎)
DROP TABLE users CASCADE;  -- SQL Server不支持此语法

5.3 清空表数据 #

sql
-- 使用DELETE(记录日志,可回滚)
DELETE FROM users;

-- 使用TRUNCATE(不记录日志,更快)
TRUNCATE TABLE users;

-- TRUNCATE与DELETE区别
/*
TRUNCATE:
- 不记录日志,速度快
- 不能用于有外键引用的表
- 重置IDENTITY值
- 不能触发触发器

DELETE:
- 记录日志,可回滚
- 可以有WHERE条件
- 不重置IDENTITY值
- 触发触发器
*/

六、临时表 #

6.1 本地临时表 #

sql
-- 创建本地临时表(#前缀)
CREATE TABLE #temp_users (
    id INT,
    name NVARCHAR(50)
);

-- 插入数据
INSERT INTO #temp_users
SELECT id, name FROM users WHERE status = 1;

-- 使用临时表
SELECT * FROM #temp_users;

-- 临时表在会话结束时自动删除
-- 也可以手动删除
DROP TABLE #temp_users;

6.2 全局临时表 #

sql
-- 创建全局临时表(##前缀)
CREATE TABLE ##global_temp (
    id INT,
    value NVARCHAR(100)
);

-- 所有会话都可以访问
INSERT INTO ##global_temp VALUES (1, 'Test');

-- 查询
SELECT * FROM ##global_temp;

-- 所有会话结束时自动删除
DROP TABLE ##global_temp;

6.3 表变量 #

sql
-- 声明表变量
DECLARE @temp_users TABLE (
    id INT,
    name NVARCHAR(50),
    PRIMARY KEY (id)
);

-- 插入数据
INSERT INTO @temp_users
SELECT id, name FROM users WHERE status = 1;

-- 使用表变量
SELECT * FROM @temp_users;

-- 表变量在批处理结束时自动销毁

6.4 临时表 vs 表变量 #

特性 临时表 表变量
作用域 会话/批处理 批处理
索引 支持创建 只能在定义时创建
事务 支持事务 不受事务影响
统计信息
性能 大数据量优 小数据量优
内存/磁盘 可能在磁盘 内存优先

七、计算列 #

7.1 创建计算列 #

sql
-- 创建计算列
CREATE TABLE products (
    id INT PRIMARY KEY,
    name NVARCHAR(100),
    price DECIMAL(10,2),
    quantity INT,
    total AS price * quantity  -- 计算列
);

-- 持久化计算列
CREATE TABLE products (
    id INT PRIMARY KEY,
    name NVARCHAR(100),
    price DECIMAL(10,2),
    quantity INT,
    total AS price * quantity PERSISTED  -- 存储计算结果
);

-- 可以在持久化计算列上创建索引
CREATE INDEX ix_products_total ON products(total);

7.2 添加计算列 #

sql
-- 添加计算列
ALTER TABLE products ADD
    discount_price AS price * 0.9;

-- 添加持久化计算列
ALTER TABLE products ADD
    total_value AS price * quantity PERSISTED;

八、标识列 #

8.1 IDENTITY属性 #

sql
-- 创建标识列
CREATE TABLE users (
    id INT IDENTITY(1,1) PRIMARY KEY,  -- 种子=1,增量=1
    name NVARCHAR(50)
);

-- 自定义种子和增量
CREATE TABLE orders (
    id INT IDENTITY(1000, 10) PRIMARY KEY,  -- 从1000开始,每次增10
    order_date DATE
);

-- 插入数据(自动生成ID)
INSERT INTO users (name) VALUES ('John');
INSERT INTO users (name) VALUES ('Jane');

SELECT * FROM users;
-- id | name
-- 1  | John
-- 2  | Jane

8.2 获取标识值 #

sql
-- 获取最后插入的标识值
INSERT INTO users (name) VALUES ('Bob');
SELECT @@IDENTITY AS [最后ID];

-- 更安全的方式(不受触发器影响)
SELECT SCOPE_IDENTITY() AS [当前作用域ID];

-- 获取表的标识值
SELECT IDENT_CURRENT('users') AS [表最后ID];

-- 重置标识值
DBCC CHECKIDENT ('users', RESEED, 0);

8.3 插入指定标识值 #

sql
-- 启用标识插入
SET IDENTITY_INSERT users ON;

INSERT INTO users (id, name) VALUES (100, 'Test');

SET IDENTITY_INSERT users OFF;

-- 查看结果
SELECT * FROM users;

九、序列 #

9.1 创建序列 #

sql
-- 创建序列(SQL Server 2012+)
CREATE SEQUENCE seq_user_id
    AS INT
    START WITH 1
    INCREMENT BY 1
    MINVALUE 1
    MAXVALUE 1000000
    CYCLE;  -- 到达最大值后循环

-- 创建不循环序列
CREATE SEQUENCE seq_order_id
    AS BIGINT
    START WITH 1000
    INCREMENT BY 1;

9.2 使用序列 #

sql
-- 获取下一个值
SELECT NEXT VALUE FOR seq_user_id;

-- 插入时使用序列
INSERT INTO users (id, name)
VALUES (NEXT VALUE FOR seq_user_id, 'John');

-- 获取当前值(不增加)
SELECT CURRENT_VALUE FROM sys.sequences WHERE name = 'seq_user_id';

-- 重置序列
ALTER SEQUENCE seq_user_id RESTART WITH 1;

9.3 序列 vs IDENTITY #

特性 IDENTITY SEQUENCE
表绑定
可重置 需要DBCC ALTER SEQUENCE
获取值 插入后 任何时候
缓存 表级 可配置
循环
多表共享

十、表分区 #

10.1 创建分区函数 #

sql
-- 创建分区函数
CREATE PARTITION FUNCTION pf_orders_by_date (DATE)
AS RANGE RIGHT FOR VALUES 
    ('2023-01-01', '2024-01-01', '2025-01-01');

10.2 创建分区方案 #

sql
-- 创建分区方案
CREATE PARTITION SCHEME ps_orders_by_date
AS PARTITION pf_orders_by_date
TO (fg_2022, fg_2023, fg_2024, fg_2025);

10.3 创建分区表 #

sql
-- 创建分区表
CREATE TABLE orders (
    id INT IDENTITY(1,1),
    order_date DATE,
    customer_id INT,
    amount DECIMAL(10,2)
) ON ps_orders_by_date(order_date);

十一、表信息查询 #

11.1 查看表结构 #

sql
-- 使用sp_help
EXEC sp_help 'users';

-- 使用sp_columns
EXEC sp_columns 'users';

-- 查询系统视图
SELECT 
    c.name AS [列名],
    t.name AS [数据类型],
    c.max_length AS [最大长度],
    c.is_nullable AS [允许NULL],
    c.is_identity AS [标识列]
FROM sys.columns c
JOIN sys.types t ON c.user_type_id = t.user_type_id
WHERE c.object_id = OBJECT_ID('users')
ORDER BY c.column_id;

11.2 查看表约束 #

sql
-- 查看约束
SELECT 
    o.name AS [约束名],
    o.type_desc AS [类型],
    c.name AS [列名]
FROM sys.objects o
LEFT JOIN sys.columns c ON o.parent_object_id = c.object_id
WHERE o.parent_object_id = OBJECT_ID('users');

-- 使用sp_helpconstraint
EXEC sp_helpconstraint 'users';

11.3 查看表依赖 #

sql
-- 查看表依赖
SELECT 
    OBJECT_NAME(referencing_id) AS [引用对象],
    referenced_entity_name AS [被引用对象]
FROM sys.sql_expression_dependencies
WHERE referenced_id = OBJECT_ID('users');

十二、最佳实践 #

12.1 表设计原则 #

text
表设计最佳实践:
├── 选择合适的数据类型
│   ├── 使用最小够用的类型
│   └── 避免过度使用NVARCHAR
│
├── 合理使用NULL
│   ├── 必填字段设置NOT NULL
│   └── 可选字段允许NULL
│
├── 主键设计
│   ├── 推荐使用INT IDENTITY
│   └── 或UNIQUEIDENTIFIER
│
├── 外键设计
│   ├── 确保数据完整性
│   └── 考虑级联操作
│
└── 索引设计
    ├── 主键自动创建聚集索引
    └── 外键列考虑创建索引

12.2 性能考虑 #

sql
-- 使用适当的数据类型
-- 好
CREATE TABLE users (
    id INT IDENTITY(1,1) PRIMARY KEY,
    status TINYINT,  -- 0-255足够
    name NVARCHAR(50)  -- 限制长度
);

-- 避免
CREATE TABLE users (
    id INT IDENTITY(1,1) PRIMARY KEY,
    status INT,  -- 浪费空间
    name NVARCHAR(MAX)  -- 无法创建索引
);

十三、总结 #

表操作要点:

操作 命令
创建表 CREATE TABLE
修改表 ALTER TABLE
删除表 DROP TABLE
清空表 TRUNCATE TABLE
添加列 ALTER TABLE ADD
修改列 ALTER TABLE ALTER COLUMN
删除列 ALTER TABLE DROP COLUMN
重命名 sp_rename

下一步,让我们学习数据插入!

最后更新:2026-03-27