sqlite数据库方法类使用说明-检查列字段是否存在、添加列、删除列

SQLite开源项目:数据库操作与字段管理示例

本文主要演示sqlite开源项目中的数据库方法类使用说明。本项目旨在分享知识和经验,欢迎广大网友一起加入到开源项目中一起分享贡献知识和经验。

线上测试代码:

/******************************************************************************
  > File Name		: samples_addfield.cpp
  > Author			: Wseldom
  > Mail			: 3235459847@qq.com
  > Created Time	: Fri 01 Dec 2023 03:06:27 PM CST
******************************************************************************/
#include "./samples_addfield.hpp"
#include "sqlite/sqlite.h"

#define	RUN_TO_HERE printf ("run to here(%d)\n", __LINE__);



int samples_addfield (int argc, char** argv)
{
	if (argc < 2) {
		printf ("请输入一个参数以指定数据库文件名!\n");
		return -1;
	}
	sql::sqlite db(argv[1]);
	db.exec ("create table if not exists employee("
		"ID INTEGER PRIMARY KEY  AUTOINCREMENT, "
		"NAME           TEXT    NOT NULL UNIQUE, "
		"AGE            INT     NOT NULL, "
		"ADDRESS        CHAR(50)"
	");");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS) VALUES(1, '张三', 18, '珠海');");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS) VALUES(NULL, '李四', 21, '广州');");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS) VALUES(NULL, '啊五', 32, '深圳');");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS) VALUES(NULL, '小哀', 23, '珠海');");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS) VALUES(NULL, '刘五', 18, '深圳');");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS) VALUES(NULL, '柯南', 43, '广州');");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS) VALUES(NULL, '苏周', 51, '广州');");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS) VALUES(NULL, '啊二', 21, '珠海');");
	printf ("检查表中字段。\n");
	if (db.check_field ("employee", "SALARY") == E_SQLITE_FALSE) {
		printf ("表employee中不存在字段SALARY,添加字段SALARY,并设置默认值为10000.\n");
		db.exec (SQLCMD_ADD_COLUMN ("employee","SALARY REAL DEFAULT 10000"));
	} else {
		printf ("表employee中已存在字段SALARY.\n");
	}
	RUN_TO_HERE
	printf ("再次检查表中字段。\n");
	RUN_TO_HERE
	if (db.check_field ("employee", "SALARY") == E_SQLITE_FALSE) {
		printf ("表employee中不存在字段SALARY.\n");
	} else {
		printf ("表employee中已存在字段SALARY.\n");
	}
	RUN_TO_HERE
	sql::query* query;
	query = db.query ("select * from employee limit 1;");
	RUN_TO_HERE
	if (query) {
		query->begin ();
		do {
			printf ("ID=%ld,NAME=%s,AGE=%ld,ADDRESS=%s,SALARY=%f\n"
				, query->get_number ("ID", 0)
				, query->get_string ("NAME", "未知")
				, query->get_number ("AGE", 0)
				, query->get_string ("ADDRESS", "地址")
				, query->get_float ("SALARY", 5000)
			);
		} while (query->next () > 0);
		delete query;
	}
	return 0;
}

首先创建表employee,表中不包含字段SALARY,然后插入一些数据;
然后调用方法check_field检查字段SALARY是否灿在,若不存在则新增此字段,并且设置默认值为10000;若存在则提示已存在。插入后重新检查字段是否存在,并且查询一条记录打印其值,看默认值是否生效。执行结果如下:
在这里插入图片描述
注意“sqlite err info:query aborted”并非查询错误,此日志是因为check_field检查到字段存在时在回调函数中返回非0导致查询终止而形成的日志。

接下来是删除表中字段的例程。

/******************************************************************************
  > File Name		: samples_delfield.cpp
  > Author			: Wseldom
  > Mail			: 3235459847@qq.com
  > Created Time	: Fri 01 Dec 2023 03:59:25 PM CST
******************************************************************************/
#include "./samples_delfield.hpp"
#include "sqlite/sqlite.h"




int samples_delfield (int argc, char** argv)
{
	if (argc < 2) {
		printf ("请输入一个参数以指定数据库文件名!\n");
		return -1;
	}
	sql::sqlite db(argv[1]);
	db.exec ("create table if not exists employee("
		"ID INTEGER PRIMARY KEY  AUTOINCREMENT, "
		"NAME           TEXT    NOT NULL UNIQUE, "
		"AGE            INT     NOT NULL, "
		"ADDRESS        CHAR(50), "
		"SALARY         REAL"
	");");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS,SALARY) VALUES(1, '张三', 18, '珠海', 2500.0);");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS,SALARY) VALUES(NULL, '李四', 21, '广州', 6800.0);");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS,SALARY) VALUES(NULL, '啊五', 32, '深圳', 16500.0);");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS,SALARY) VALUES(NULL, '小哀', 23, '珠海', 13000.0);");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS,SALARY) VALUES(NULL, '刘五', 18, '深圳', 4500.0);");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS,SALARY) VALUES(NULL, '柯南', 43, '广州', 20500.0);");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS,SALARY) VALUES(NULL, '苏周', 51, '广州', 22500.0);");
	db.exec ("INSERT INTO employee(ID,NAME,AGE,ADDRESS,SALARY) VALUES(NULL, '啊二', 21, '珠海', 12500.0);");


	printf ("删除字段SALARY");
	db.exec ("create table temp as select ID,NAME,AGE,ADDRESS from employee where 1 = 1;");
	db.exec ("drop table employee;");
	db.exec (SQLCMD_RENAME_TABLE("temp", "employee"));

	if (db.check_field ("employee", "SALARY") == E_SQLITE_FALSE) {
		printf ("表employee中已不存在字段SALARY.\n");
	} else {
		printf ("表employee中存在字段SALARY.\n");
	}

	sql::query* query = NULL;
	query = db.query ("select * from employee;");
	if (query == NULL) {
		printf ("查询失败或未查询到数据!\n");
		return -1;
	}
	if (query->size () <= 0) {
		delete query;
		printf ("未查询到数据!\n");
		return -1;
	}
	printf ("总共查询到%d条记录,记录如下:\n", query->size ());
	query->begin ();
	do {
		printf ("ID:%ld, name:%s, age:%ld, address:%s, salary:%f\n"
		, query->get_number ("ID", 0)
		, query->get_string ("name", "")
		, query->get_number ("age", 0)
		, query->get_string ("address", "")
		, query->get_float ("salary", 0)
		);
	} while (query->next () > 0);
	delete query;
	return 0;
}

执行结果如下:
在这里插入图片描述

<think>我们被要求使用C#和SQLite来判断数据库表中是否存在,如果不存在添加。 根据引用[2]中的方法,我们可以通过查询sqlite_master表来检查是否存在。在SQLite中,表的定义存储在sqlite_master表中,我们可以查询这个表的sql字段,该字段包含了创建表的SQL语句。如果该SQL语句中包含我们要找的名,那么该存在。 但是,需要注意的是,直接检查sql字段的字符串是否包含名可能会误匹配(例如,名可能是其他名的一部分),因此我们可以使用更精确的匹配方式(如使用LIKE操作符并加上适当的通配符和边界)。 然而,在C#中,我们可以通过执行一个查询检查是否存在。具体步骤如下: 1. 打开数据库连接。 2. 执行一个查询,从sqlite_master表中查找目标表,并检查其sql字段中是否包含目标名的定义。 3. 如果查询结果为空,则表示该存在,然后执行ALTER TABLE语句来添加。 但是,引用[2]中使用了Java和JDBC的示例,我们需要将其转换为C#和SQLite.NET的代码。 在C#中,我们可以使用SQLite.NET库(例如System.Data.SQLite或Microsoft.Data.Sqlite)。这里以Microsoft.Data.Sqlite为例,因为它是轻量级的,且支持.NET Core和.NET 5+。 步骤: 1. 确保已经安装了Microsoft.Data.Sqlite NuGet包。 2. 使用SqliteConnection打开数据库连接。 3. 编写查询语句,检查目标表的创建SQL中是否包含目标(注意:这里需要小心,因为名可能是其他名的一部分,所以我们可以用空格或逗号等分隔符来帮助匹配,但更可靠的方法是解析SQL,然而SQLite没有直接提供检查是否存在的函数,所以通常采用检查sql字段的方法)。 4. 执行查询,如果不存在则执行ALTER TABLE添加。 但是,更安全的做法是使用PRAGMA table_info(table_name)来获取表的信息,然后检查是否在结果集中。 我们可以使用以下步骤: 1. 使用PRAGMA table_info(table_name)查询表的所有信息。 2. 遍历结果集,检查是否存在。 3. 如果不存在,则执行ALTER TABLE语句。 使用PRAGMA table_info(table_name)会返回一个结果集,包含表中的信息,其中每一行代表一,包括名、数据类型等信息。 因此,我们可以这样做: 示例代码: using (var connection = new SqliteConnection("Data Source=your_database.db")) { connection.Open(); string tableName = "YourTable"; string columnName = "NewColumn"; string columnType = "TEXT"; // 例如,要添加的数据类型 // 检查是否存在 var command = connection.CreateCommand(); command.CommandText = $"PRAGMA table_info({tableName})"; using (var reader = command.ExecuteReader()) { bool columnExists = false; while (reader.Read()) { // 名在索引1的位置(因为PRAGMA table_info返回的有:cid, name, type, notnull, dflt_value, pk) var name = reader.GetString(1); if (name == columnName) { columnExists = true; break; } } if (!columnExists) { // 执行添加的操作 var alterCommand = connection.CreateCommand(); alterCommand.CommandText = $"ALTER TABLE {tableName} ADD COLUMN {columnName} {columnType}"; alterCommand.ExecuteNonQuery(); Console.WriteLine($"已添加 {columnName}"); } else { Console.WriteLine($" {columnName} 已存在"); } } } 注意:表名和名在SQL语句中通常不需要用引号,除非它们包含特殊字符。如果表名或名是保留字或包含特殊字符,则需要用方括号[]或双引号""括起来。但是为了简单,我们假设表名和名都是简单的标识符。 另外,使用PRAGMA table_info是更可靠的方法,因为它直接提供了的信息,避免了字符串匹配可能带来的问题。 因此,我们推荐使用PRAGMA table_info来检查是否存在。 但是,请注意,在SQLite中,PRAGMA语句在同一个连接中可能不会立即更新,但在这里我们是在同一个连接中先检查后修改,所以没有问题。 所以,我们可以按照上述代码来实现。 另外,引用[1]中提到了使用SQLite.NET的ORM方式(Table<T>),但这里我们直接使用SQL命令,因为PRAGMA语句不能通过ORM方式执行。 因此,最终代码将如上所示。 注意:在实际应用中,可能需要处理异常,比如表不存在等情况。 下面我们提供一个更完整的函数: 函数:检查添加(如果不存在) 参数:数据库连接字符串(或连接对象)、表名、名、类型 这里我们假设使用连接对象,但也可以打开连接。 示例函数: public static void AddColumnIfNotExists(SqliteConnection connection, string tableName, string columnName, string columnType) { // 确保连接是打开的 if (connection.State != System.Data.ConnectionState.Open) connection.Open(); // 检查是否存在 bool columnExists = false; var command = connection.CreateCommand(); command.CommandText = $"PRAGMA table_info({tableName})"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { if (reader.GetString(1) == columnName) { columnExists = true; break; } } } if (!columnExists) { var alterCommand = connection.CreateCommand(); alterCommand.CommandText = $"ALTER TABLE {tableName} ADD COLUMN {columnName} {columnType}"; alterCommand.ExecuteNonQuery(); Console.WriteLine($" {columnName} 添加成功"); } else { Console.WriteLine($" {columnName} 已存在,无需添加"); } } 然后我们可以这样调用: using (var connection = new SqliteConnection("Data Source=test.db")) { connection.Open(); AddColumnIfNotExists(connection, "MyTable", "NewColumn", "TEXT"); } 注意:在实际应用中,可能需要对表名和名进行适当的转义,以防止SQL注入(如果表名或名来自用户输入)。但通常表名和名是程序内部定义的,所以问题不大。如果确实需要处理用户输入的表名或名,应该使用参数化,但PRAGMA和ALTER TABLE语句不支持参数化表名和名。因此,我们需要对表名和名进行严格的检查(例如,只允许字母数字和下划线),或者使用白名单。 另外,SQLite的ALTER TABLE功能有限,只能添加,不能删除或修改。 以上就是在C#中使用SQLite判断表是否存在添加的方法。 相关问题: 1. 在SQLite中如何删除一个? 2. 如何修改SQLite表中已存在? 3. 在SQLite中如何重命名一个? 注意:SQLite的ALTER TABLE只支持重命名表和添加,不支持删除和修改。如果需要删除或修改,通常需要创建新表,复制数据,然后删除旧表并重命名新表。</think>在 C# 中使用 SQLite 判断表是否存在并动态添加,可通过查询 `sqlite_master` 系统表或使用 `PRAGMA table_info()` 实现。以下是完整解决方案: ### 方法 1:查询 sqlite_master(推荐) ```csharp using System.Data.SQLite; public void AddColumnIfNotExists(string tableName, string columnName, string columnType) { using (var conn = new SQLiteConnection("Data Source=your_database.db")) { conn.Open(); // 检查是否存在 string checkSql = $@" SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='{tableName}' AND sql LIKE '%{columnName}%'"; using (var cmd = new SQLiteCommand(checkSql, conn)) { int exists = Convert.ToInt32(cmd.ExecuteScalar()); if (exists == 0) // 存在 { // 添加 string alterSql = $"ALTER TABLE {tableName} ADD COLUMN {columnName} {columnType}"; new SQLiteCommand(alterSql, conn).ExecuteNonQuery(); Console.WriteLine($"已添加: {columnName}"); } else { Console.WriteLine($"存在: {columnName}"); } } } } ``` ### 方法 2:使用 PRAGMA table_info() ```csharp using System.Data.SQLite; public void AddColumnIfNotExists(string tableName, string columnName, string columnType) { using (var conn = new SQLiteConnection("Data Source=your_database.db")) { conn.Open(); // 获取表的所有信息 string pragmaSql = $"PRAGMA table_info({tableName})"; bool columnExists = false; using (var cmd = new SQLiteCommand(pragmaSql, conn)) using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { if (reader.GetString(1) == columnName) // 索引1对应名 { columnExists = true; break; } } } if (!columnExists) { string alterSql = $"ALTER TABLE {tableName} ADD COLUMN {columnName} {columnType}"; new SQLiteCommand(alterSql, conn).ExecuteNonQuery(); Console.WriteLine($"已添加: {columnName}"); } } } ``` ### 使用示例 ```csharp // 在Users表中添加Phone(如果不存在) AddColumnIfNotExists("Users", "Phone", "TEXT"); ``` ### 关键说明 1. **安全注意事项**: - 表名/名应使用白名单验证,防止SQL注入 - 避免保留字作为标识符(如需使用需用方括号包裹:`[Order]`) 2. **SQLite限制**: - 不支持直接删除(需创建新表迁移数据)[^1] - `ALTER TABLE` 仅支持添加和重命名表[^2] 3. **性能建议**: - 频繁操作时复用数据库连接 - 批量添加时建议合并检查逻辑 ### 工作流程 ```mermaid graph TD A[开始] --> B[打开数据库连接] B --> C{检查是否存在} C -->|存在| D[输出提示信息] C -->|不存在| E[执行ALTER TABLE添加] E --> F[输出添加成功信息] D --> G[结束] F --> G ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值