sql 表中的列与现存的主键或unique约束不匹配

本文介绍了解决SQL数据库中主键与外键不匹配的问题,通过正确设置主键顺序并调整外键引用,确保数据库关系的一致性和有效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     今天在更新项目时需要修改数据库中表的主键,结果报出sql 表中的列与现存的主键或unique约束不匹配。

     表LN003075原有主键,唯一索引,其中

     原有主键字段是:[MCLASS_ID],
                             [BCLASS_ID],
                             [SYSTEM_ID]

     唯一索引是:      [BCLASS_ID],
                             [SYSTEM_ID]

    跟表LN003078有关系:

 FK_STYLE_BCLASS FOREIGN KEY
 (
 BCLASS_ID,
 SYSTEM_ID
 ) REFERENCES dbo.LN003075
 (
 BCLASS_ID,
 SYSTEM_ID
 )

这里, 表LN003075的主键与唯一索引显然是不合理,一个表应该只有一个唯一索引。于是要更改主键为:

[BCLASS_ID],
[SYSTEM_ID]

去除原有的唯一索引。

思路是:先去除与表LN003078的关系,然后删除主键,唯一索引,接着重新新主键,最后重建与表LN003078的关系。

由于粗心,写关系的时候弄成了

 FK_STYLE_BCLASS FOREIGN KEY
 (

 SYSTEM_ID,
 BCLASS_ID

  ) REFERENCES dbo.LN003075
 (
 SYSTEM_ID,
 BCLASS_ID
 )

在重建关系的时候报出sql 表中的列与现存的主键或unique约束不匹配。这个原因就是因为没有与主键的次序一致造成的,应该是:

 FK_STYLE_BCLASS FOREIGN KEY
 (
 BCLASS_ID,
 SYSTEM_ID
 ) REFERENCES dbo.LN003075
 (
 BCLASS_ID,
 SYSTEM_ID
 )

 

好了。贴出所有SQL语法如下:

 

 

<think>我们正在将一个使用文本文件存储的C#学生管理系统改造为使用SQLite数据库存储。我们将使用VS2019,并需要将现有的数据持久化方式从文本文件迁移到SQLite。 步骤: 1. 添加SQLite支持:通过NuGet安装System.Data.SQLite包。 2. 设计数据库:创建学生,考虑原有文本文件存储的数据结构。 3. 实现数据访问层:将原来对文本文件的读写操作替换为SQLite数据库操作。 4. 迁移现有数据:如果原有文本文件中有数据,需要编写一个迁移程序将数据导入SQLite数据库。 5. 测试:确保所有功能正常。 假设原有的学生信息存储格式为:每行一个学生,字段用逗号分隔(例如:学号,姓名,年龄,成绩)。 详细步骤: 第一步:安装SQLite 在VS2019中,打开NuGet包管理器控制台,执行: ``` Install-Package System.Data.SQLite ``` 第二步:创建数据库 我们可以在程序第一次运行时创建数据库。假设数据库名为"StudentDB.sqlite",结构如下: ```sql CREATE TABLE IF NOT EXISTS Students ( Id INTEGER PRIMARY KEY AUTOINCREMENT, StudentId TEXT NOT NULL UNIQUE, Name TEXT NOT NULL, Age INTEGER, Score REAL ); ``` 注意:这里我们使用自增整数主键(Id),同时要求学号(StudentId)唯一。 第三步:实现数据访问层 我们需要实现以下基本操作: - 添加学生 - 删除学生 - 修改学生信息 - 查询学生 我们将创建一个类(例如StudentRepository)来封装这些操作。 第四步:数据迁移 如果原有文本文件(比如students.txt)中有数据,我们需要读取该文件,并将每一行解析为一个学生对象,然后插入到数据库中。 第五步:修改原有代码 将原来操作文本文件的地方改为调用新的数据访问层。 代码示例: 1. 创建数据库连接字符串: string connectionString = "Data Source=StudentDB.sqlite;Version=3;"; 2. 创建StudentRepository类,包含基本的CRUD方法。 3. 在Main方法中,检查数据库是否存在,如果存在则创建,并执行数据迁移(如果有旧数据文件)。 下面是一个简单的代码框架: 首先,定义学生类(如果还没有): ```csharp public class Student { public string StudentId { get; set; } public string Name { get; set; } public int Age { get; set; } public double Score { get; set; } } ``` 然后,创建数据访问类: ```csharp using System.Data.SQLite; public class StudentRepository { private string connectionString; public StudentRepository(string dbFilePath) { connectionString = $"Data Source={dbFilePath};Version=3;"; InitializeDatabase(); } private void InitializeDatabase() { using (var connection = new SQLiteConnection(connectionString)) { connection.Open(); string createTableQuery = @" CREATE TABLE IF NOT EXISTS Students ( Id INTEGER PRIMARY KEY AUTOINCREMENT, StudentId TEXT NOT NULL UNIQUE, Name TEXT NOT NULL, Age INTEGER, Score REAL )"; using (var command = new SQLiteCommand(createTableQuery, connection)) { command.ExecuteNonQuery(); } } } public void AddStudent(Student student) { using (var connection = new SQLiteConnection(connectionString)) { connection.Open(); string query = "INSERT INTO Students (StudentId, Name, Age, Score) VALUES (@studentId, @name, @age, @score)"; using (var command = new SQLiteCommand(query, connection)) { command.Parameters.AddWithValue("@studentId", student.StudentId); command.Parameters.AddWithValue("@name", student.Name); command.Parameters.AddWithValue("@age", student.Age); command.Parameters.AddWithValue("@score", student.Score); command.ExecuteNonQuery(); } } } // 其他方法:Update, Delete, GetAllStudents等 } ``` 数据迁移方法(在StudentRepository中单独的工具类中): ```csharp public void MigrateFromTextFile(string filePath) { if (!File.Exists(filePath)) return; var lines = File.ReadAllLines(filePath); foreach (var line in lines) { var parts = line.Split(','); if (parts.Length < 4) continue; var student = new Student { StudentId = parts[0], Name = parts[1], Age = int.Parse(parts[2]), Score = double.Parse(parts[3]) }; AddStudent(student); } // 迁移完成后,可以备份删除原文件 File.Move(filePath, filePath + ".bak"); } ``` 最后,在程序入口调用: ```csharp static void Main(string[] args) { string dbFile = "StudentDB.sqlite"; var repository = new StudentRepository(dbFile); // 如果存在旧的文本文件,则迁移 string oldDataFile = "students.txt"; if (File.Exists(oldDataFile)) { repository.MigrateFromTextFile(oldDataFile); } // 然后进入主程序(如菜单等) } ``` 注意:在实际项目中,我们还需要处理异常,比如数据库操作可能出现的异常,以及数据转换的异常。 这样,我们就完成了从文本文件存储到SQLite数据库的改造。 相关问题: 1. 如何优化SQLite数据库的性能? 2. 在C#中使用SQLite有哪些常见错误?如何避免? 3. 如何设计一个更复杂的学生管理系统数据库(比如加入课程、成绩等)? 4. SQLite数据库如何实现多线程访问?</think>### C# 学生管理系统:SQLite 替代文本文件存储实现指南 #### 1. **环境准备**(VS2019) ```csharp // 步骤1:安装 NuGet 包 Install-Package System.Data.SQLite ``` - 在 NuGet 包管理器中搜索安装 `System.Data.SQLite` #### 2. **数据库设计** ```sql CREATE TABLE Students ( Id INTEGER PRIMARY KEY AUTOINCREMENT, StudentId TEXT NOT NULL UNIQUE, -- 学号 Name TEXT NOT NULL, Age INTEGER, Score REAL, CreatedTime DATETIME DEFAULT CURRENT_TIMESTAMP ); ``` #### 3. **数据访问层改造** ```csharp using System.Data.SQLite; public class StudentRepository { private const string ConnectionString = "Data Source=StudentDB.sqlite;Version=3;"; // 初始化数据库 public void InitializeDatabase() { using (var conn = new SQLiteConnection(ConnectionString)) { conn.Open(); string sql = @"CREATE TABLE IF NOT EXISTS Students (...)"; // 使用上结构 new SQLiteCommand(sql, conn).ExecuteNonQuery(); } } // 添加学生 public void AddStudent(Student student) { using (var conn = new SQLiteConnection(ConnectionString)) { conn.Open(); string sql = @"INSERT INTO Students (StudentId, Name, Age, Score) VALUES (@id, @name, @age, @score)"; var cmd = new SQLiteCommand(sql, conn); cmd.Parameters.AddWithValue("@id", student.StudentId); // ... 其他参数 cmd.ExecuteNonQuery(); } } // 查询所有学生 public List<Student> GetAllStudents() { var students = new List<Student>(); using (var conn = new SQLiteConnection(ConnectionString)) { conn.Open(); string sql = "SELECT * FROM Students"; using (var reader = new SQLiteCommand(sql, conn).ExecuteReader()) { while (reader.Read()) { students.Add(new Student { StudentId = reader["StudentId"].ToString(), Name = reader["Name"].ToString(), Age = Convert.ToInt32(reader["Age"]), Score = Convert.ToDouble(reader["Score"]) }); } } } return students; } } ``` #### 4. **数据迁移(文本→SQLite)** ```csharp public void MigrateTextToSQLite(string textFilePath) { var lines = File.ReadAllLines(textFilePath); foreach (var line in lines) { var data = line.Split(','); var student = new Student { StudentId = data[0], Name = data[1], Age = int.Parse(data[2]), Score = double.Parse(data[3]) }; AddStudent(student); // 调用插入方法 } } ``` #### 5. **业务层改造** ```csharp // 原文本文件操作(需替换) // File.WriteAllText("students.txt", ...); // 新SQLite操作 var repo = new StudentRepository(); repo.AddStudent(newStudent); // 添加学生 var allStudents = repo.GetAllStudents(); // 查询学生 ``` #### 6. **性能优化建议** 1. **连接池管理**:SQLite 默认启用连接池,避免频繁开关连接 2. **事务批处理**:批量操作时使用事务 ```csharp using (var transaction = conn.BeginTransaction()) { foreach (var student in students) { // 执行插入命令 } transaction.Commit(); } ``` 3. **参数化查询**:始终使用 `Parameters` 防止 SQL 注入 #### 7. **部署注意事项** - 将生成的 `StudentDB.sqlite` 文件放入输出目录 - 添加配置文件指定数据库路径: ```xml <appSettings> <add key="DatabasePath" value="Data\StudentDB.sqlite"/> </appSettings> ``` #### 8. **测试验证** ```csharp // 单元测试示例 [TestMethod] public void TestStudentInsert() { var repo = new StudentRepository(); repo.AddStudent(new Student { StudentId = "2023001", ... }); var result = repo.GetStudentById("2023001"); Assert.IsNotNull(result); } ``` > **改造收益**: > 1. 数据一致性:通过事务保证操作原子性 > 2. 查询效率:复杂查询速度提升 $O(n)\to O(\log n)$ > 3. 并发支持:文件锁机制优化多用户访问[^1]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值