单语句创建CD商店数据库失败求助:USE语句报错
问题分析与解决方法
Hey,我看到你在创建CD商店数据库的单脚本里遇到了USE CDCI的报错,作为入门级开发者,这个问题其实是SQL Server批处理机制的常见坑,我来帮你一步步解决,顺便给你一些实操技巧。
核心错误原因:批处理分隔问题
在SQL Server中,CREATE DATABASE是一个独立的批处理操作,必须用GO分隔后才能执行USE命令。你当前的脚本里CREATE DATABASE之后直接写USE CDCI,没有用GO分隔,导致数据库还没完全创建好就尝试切换,所以报错。另外你脚本里重复的USE CDCI和错误的注释(>An error occurs here)也需要清理掉。
修正后的完整可执行脚本
我已经帮你修正了所有问题,你可以直接运行这个脚本:
-- 创建CDCI数据库 CREATE DATABASE CDCI ON PRIMARY( Name = cddukkan_data, FileName = 'C:\Program Files\Microsoft SQL Server\MSSQL14.VERITABANIM\MSSQL\DATA\cdci.mdf', Size = 16 MB, FileGrowth = 1 MB, MaxSize = 1 GB ) LOG ON( Name = cddukkan_log, FileName = 'C:\Program Files\Microsoft SQL Server\MSSQL14.VERITABANIM\MSSQL\DATA\cdci.ldf', Size = 8 MB, FileGrowth = 5%, MaxSize = 512 MB ) GO -- 必须加GO,确保数据库创建完成后再执行后续操作 -- 切换到CDCI数据库 USE CDCI GO -- 影片类型表 CREATE TABLE Turler( TurID INT IDENTITY(1, 1) NOT NULL, TurAdi NVARCHAR(10) NOT NULL, PRIMARY KEY(TurID) -- 主键本身就是唯一的,不需要重复写UNIQUE(TurID) ) GO -- 导演表 CREATE TABLE Yonetmenler( YonetmenID INT IDENTITY(1, 1) NOT NULL, YonetmenAdi NVARCHAR(10) NOT NULL, YonetmenSoyadi NVARCHAR(10) NULL, DogumYili NCHAR(4), -- 给约束起个有意义的名字,方便后续维护 CONSTRAINT CK_Yonetmenler_DogumYili CHECK(DogumYili LIKE '19__' OR (DogumYili LIKE '20__' AND DogumYili < CAST(YEAR(GETDATE()) - 18 AS NCHAR(4)))), Cinsiyet NCHAR(5), CONSTRAINT CK_Yonetmenler_Cinsiyet CHECK(Cinsiyet LIKE '[Ee]%' OR Cinsiyet LIKE '[Kk]%'), PRIMARY KEY(YonetmenID) ) GO -- 货架表 CREATE TABLE Raflar( RafID INT IDENTITY(1, 1) NOT NULL, RafTuru INT FOREIGN KEY REFERENCES Turler(TurID) NOT NULL, PRIMARY KEY(RafID) ) GO -- 影片表 CREATE TABLE Filmler( FilmID INT IDENTITY(1, 1) NOT NULL, FilmAdi NVARCHAR(10) NOT NULL, TurID INT FOREIGN KEY REFERENCES Turler(TurID) NOT NULL, YonetmenID INT FOREIGN KEY REFERENCES Yonetmenler(YonetmenID) NOT NULL, RafID INT FOREIGN KEY REFERENCES Raflar(RafID) NOT NULL, Fiyat MONEY NOT NULL, PRIMARY KEY(FilmID) ) GO -- 客户表 CREATE TABLE Musteriler( MusteriID INT IDENTITY(1, 1) NOT NULL, MusteriAdi NVARCHAR(10) NOT NULL, MusteriSoyadi NVARCHAR(10) NOT NULL, Adresi NVARCHAR(20), Telefon NVARCHAR(10), CONSTRAINT CK_Musteriler_Telefon CHECK(Telefon NOT LIKE '0%'), PRIMARY KEY(MusteriID) ) GO -- 演员表 CREATE TABLE Oyuncular( OyuncuID INT IDENTITY(1, 1) NOT NULL, OyuncuAdi NVARCHAR(10) NOT NULL, OyuncuSoyadi NVARCHAR(10) NULL, DogumYili NCHAR(4), -- 修正类型转换,避免字符串和数字直接比较的错误 CONSTRAINT CK_Oyuncular_DogumYili CHECK(DogumYili LIKE '19%' OR CAST(DogumYili AS INT) < YEAR(GETDATE())), PRIMARY KEY(OyuncuID) ) GO -- 销售记录表 CREATE TABLE Satislar( SatisID INT IDENTITY(1, 1) NOT NULL, FilmID INT FOREIGN KEY REFERENCES Filmler(FilmID) NOT NULL, MusteriID INT FOREIGN KEY REFERENCES Musteriler(MusteriID) NOT NULL, SatisAdedi INT NOT NULL, PRIMARY KEY(SatisID) -- 给销售记录加主键,确保每条记录唯一 ) GO -- 影片-演员关联表(多对多关系) CREATE TABLE FilmOyuncu( FilmID INT FOREIGN KEY REFERENCES Filmler(FilmID) NOT NULL, OyuncuID INT FOREIGN KEY REFERENCES Oyuncular(OyuncuID) NOT NULL, PRIMARY KEY(FilmID, OyuncuID) -- 多对多表必须用复合主键,避免重复关联 ) GO -- 客户电话格式检查触发器 CREATE TRIGGER [TelefonKontrol] ON [Musteriler] FOR INSERT AS BEGIN -- 原脚本用单个变量只能处理单行插入,改成EXISTS支持批量插入 IF EXISTS(SELECT 1 FROM INSERTED WHERE Telefon LIKE '0%') BEGIN PRINT 'Lütfen telefon numarasını başına 0 rakamı koymayınız.' ROLLBACK TRAN END END GO -- 影片货架类型匹配检查触发器 CREATE TRIGGER [FilmRafTuruUyumu] ON [Filmler] FOR INSERT AS BEGIN -- 同样处理多行插入的情况 IF EXISTS( SELECT 1 FROM INSERTED i JOIN Raflar r ON i.RafID = r.RafID WHERE r.RafTuru <> i.TurID ) BEGIN PRINT 'Lütfen film uygun rafa yerleştiriniz!' ROLLBACK TRAN END END GO
关键修改点说明
- 批处理分隔:在
CREATE DATABASE后添加GO,确保数据库完全创建完成后再执行USE和后续表创建操作,这是解决你报错的核心。 - 去除冗余约束:主键(
PRIMARY KEY)本身就自带唯一性,所以不需要重复定义UNIQUE,减少冗余代码。 - 约束命名规范:给所有约束手动命名(比如
CK_Yonetmenler_DogumYili),比系统自动生成的名字更容易识别,后续排查约束错误时更方便。 - 类型转换修正:在
DogumYili的约束中,把数字年份转换成字符串类型再和DogumYili比较,避免隐式转换导致的错误。 - 触发器优化:原触发器用单个变量存储值,只能处理单行插入,改成
EXISTS检查后,能支持批量插入的场景,避免逻辑漏洞。 - 完善表结构:给
Satislar添加主键,给FilmOyuncu添加复合主键,确保数据的完整性和唯一性。
给入门开发者的实操技巧与建议
- 重视批处理
GO:SQL Server中GO是批处理分隔符,每个批处理是独立执行的。像CREATE DATABASE、CREATE TABLE这类DDL操作,一定要用GO分隔,确保前一个操作完成后再执行下一个。 - 约束命名要规范:不要依赖系统自动生成的约束名称,手动命名能让你在后续维护时快速定位问题。
- 触发器要考虑多行操作:永远不要假设触发器只会处理单行数据,实际业务中经常会有批量插入/更新,所以要用集合操作(比如
EXISTS、JOIN)代替单个变量。 - 分段测试脚本:写复杂脚本时,不要一次性运行全部,可以分段执行(比如先创建数据库,再逐个创建表),这样更容易定位错误位置。
- 检查文件路径权限:确保SQL Server服务账户有你指定的文件路径的读写权限,否则数据库创建会失败。
- 多写注释:给脚本添加注释,说明每个表、约束、触发器的作用,方便自己和他人后续维护。
内容的提问来源于stack exchange,提问作者user10911520
相关产品推荐
相关产品推荐

