kali里面docker拉了一个,怎么搭建把命令甩ai就行,启动命令如下:
sudo docker exec -it sqlserver /opt/mssql-tools18/bin/sqlcmd -S localhost -U SA -P 'Kali@2026Sec!' -C
建立库和表
首先还是创建数据库:
sql
CREATE DATABASE testdb;
GO
这里的GO是确保命令立即生效,可以从下面的截图中看到输入第一行回车之后变成了第二行,说明这整一个语句还没有结束,这个GO会告诉sqlcmd将之前输入的所有T-SQL语句作为一个批次发送给服务器执行

然后是切换到刚刚建立的数据库:
sql
USE testdb;
GO
可以看到在命令行中会有相应的提示:

再之后是建表:
sql
CREATE TABLE Employees (
ID INT PRIMARY KEY IDENTITY(1,1),
Name VARCHAR(50),
Age INT
);
这里面后两个好理解,关键是第一行:
| 部分 | 含义 | 底层解释 |
|---|---|---|
| ID | 列名 | 这一列的名称叫做 "ID" |
| INT | 数据类型 | 整数类型(Integer),取值范围约为 -21亿 到 21亿 |
| PRIMARY KEY | 主键约束 | 唯一标识每一行,值必须 唯一且非空 。数据库会自动为该列创建 聚集索引(Clustered Index),数据在物理存储上按该列顺序排列 |
| IDENTITY(1,1) | 自增属性 | (1,1) 表示:起始值为 1,每次递增 1。插入数据时无需手动指定该列值,数据库会自动生成顺序编号:1, 2, 3, 4...,保证永不重复 |
主键约束和自增属性也可以不加,如果不加主键约束的话就代表会产生以下效果:
- 允许重复的 ID 值(插入两行 ID=1 都可以)
- 允许 ID 为 NULL
- 没有唯一标识每一行的保障
- 查询大量数据时速度会慢(因为没有自动创建聚集索引)
自增不加的话就代表每次要手动指定ID的值,命令如下:
sql
INSERT INTO Employees (ID, Name, Age) VALUES (1, 'Alice', 30);
INSERT INTO Employees (ID, Name, Age) VALUES (2, 'Bob', 25);
如果加了主键约束的话需要确保每次加入的id值不相同
那么再回到最开始的命令,后面就是在表格中填入相应的内容,然后进行查看:
sql
INSERT INTO Employees (Name, Age) VALUES ('Alice', 30);
INSERT INTO Employees (Name, Age) VALUES ('Bob', 25);
GO
SELECT * FROM Employees;
GO

更新和删除
UPDATE
更新的语法如下:
sql
UPDATE 表名 SET 列名 = 新值 WHERE 条件;
那么比如将Alice的年龄改为31:
sql
UPDATE Employees SET Age=31 where Name='Alice';
go

或者将原来的Bob改为另一个人
sql
UPDATE Employees SET Name = 'ShoreKiten' WHERE Age=25;
UPDATE Employees SET Name = 'ShoreKiten' WHERE ID=2;
UPDATE Employees SET Name = 'ShoreKiten' WHERE Name='Bob';
如果where没有写的话那就是全部数据都进行更改
sql
UPDATE Employees SET Age=18;
go

DELETE
语法如下:
sql
DELETE FROM 表名 WHERE 条件;
删除Alice的数据:
sql
DELETE FROM Employees WHERE Name = 'Alice';
GO

这里也可以看到Shorekiten的ID仍为2,并没有因为前一个数据的删除而减少
还有一种删除方法是对全表进行删除但保留表原来的结构
sql
TRUNCATE TABLE Employees;
GO

WHERE进阶查询
先往表里面加几条数据,因为之前全删了因此把最开始的也放进来
sql
INSERT INTO Employees (Name, Age) VALUES ('Alice', 30);
INSERT INTO Employees (Name, Age) VALUES ('Bob', 25);
INSERT INTO Employees (Name, Age) VALUES ('David', 35);
INSERT INTO Employees (Name, Age) VALUES ('Eva', 28);
INSERT INTO Employees (Name, Age) VALUES ('Frank', 42);
INSERT INTO Employees (Name, Age) VALUES ('Grace', 23);
INSERT INTO Employees (Name, Age) VALUES ('Henry', 31);
INSERT INTO Employees (Name, Age) VALUES ('Ivy', 29);
GO

AND / OR(组合条件)
sql
SELECT * FROM Employees WHERE Age > 25 AND Age < 35;
GO
SELECT * FROM Employees WHERE Age < 25 OR Age > 40;
GO

IN(在某个集合中)
sql
-- 年龄是 25、30、35 的人
SELECT * FROM Employees WHERE Age IN (25, 30, 35);
GO
-- 等价于用 OR 写
SELECT * FROM Employees WHERE Age = 25 OR Age = 30 OR Age = 35;
GO

BETWEEN(区间范围,包含边界)
sql
SELECT * FROM Employees WHERE Age BETWEEN 25 AND 35;
GO

LIKE(模糊匹配)
sql
-- 名字以 'A' 开头的人
SELECT * FROM Employees WHERE Name LIKE 'A%';
GO
-- 名字包含 'a' 的人(不区分大小写)
SELECT * FROM Employees WHERE Name LIKE '%a%';
GO
-- 名字以 'y' 结尾的人
SELECT * FROM Employees WHERE Name LIKE '%y';
GO

IS NULL / IS NOT NULL(空值判断)
先加一条有空值的测试数据:
sql
INSERT INTO Employees (Name, Age) VALUES ('Jack', NULL);
GO
-- 查询 Age 为空的人
SELECT * FROM Employees WHERE Age IS NULL;
GO
-- 查询 Age 不为空的人
SELECT * FROM Employees WHERE Age IS NOT NULL;
GO

NOT(取反)
sql
SELECT * FROM Employees WHERE Age NOT IN (25, 30, 35);
SELECT * FROM Employees WHERE age NOT BETWEEN 25 AND 35;
SELECT * FROM Employees WHERE Name NOT LIKE 'A%';

排序(ORDER BY)
sql
-- 按年龄升序排列(默认 ASC)
SELECT * FROM Employees ORDER BY Age;
GO
-- 按年龄降序排列(DESC)
SELECT * FROM Employees ORDER BY Age DESC;
GO
-- 先按年龄降序,年龄相同再按名字升序【字母表顺序】
SELECT * FROM Employees ORDER BY Age DESC, Name ASC;
GO

分页(OFFSET FETCH)
分页公式:
每页 N 条,查第 P 页:OFFSET (P-1) * N ROWS FETCH NEXT N ROWS ONLY
例如第 3 页,每页 5 条:OFFSET 10 ROWS FETCH NEXT 5 ROWS ONLY
注意: OFFSET FETCH 必须有 ORDER BY 配合
sql
-- 跳过前 3 条,取接下来 3 条(第 2 页,每页 3 条)
SELECT * FROM Employees
ORDER BY ID
OFFSET 3 ROWS
FETCH NEXT 3 ROWS ONLY;
GO

最后小综合一下,就不给答案了:
查询出:年龄在 25 到 35 之间,名字以 'A' 开头或包含 'e',按年龄降序排列,只显示前 3 条