从文件中解析并执行 Sql 语句

本文关键字:执行 Sql 语句 文件 | 更新日期: 2023-09-27 18:36:15

我正在编写一个SQL执行模块,这是医疗应用程序的一部分。

模块

  1. 接受加密的.sql文件名作为输入。该文件将包含dml语句,如插入行/更新行,注释(下面的示例)
  2. 解密文件
  3. 准备 SQL 语句列表并执行,忽略注释行(以 --开头的行)
  4. 出现错误时弹出行号

所采用的方法

  1. 加载 sqlfile 和解密是可以且完整的
    使用简单的File.ReadAllText和预构建的解密模块
  2. 准备列表是模块失败的地方。我使用了以下代码:

    string[] dmllines = dml.Split(new string[] { ";'r'n", ";'n" }, StringSplitOptions.RemoveEmptyEntries);
    

    它会导致执行忽略由于拆分方式而在注释之后出现的 SQL。

不能仅从换行符中拆分数据,因为插入语句的列值中有换行符。分号也是如此

  • DB: Postgres9.0.4
  • 代码: .NET 4.0, C#, Npgsql

欢迎任何解决方案帮助

谢谢

编辑1:我想补充一点,没有任何可能使用第三方库,实用程序,即使是postgres。
EDIT2:我正在研究一种使用正则表达式或只是 while 循环来解析字符

的可能性

示例数据如下


-- 姓名:activitylog_recordid_seq;类型:序列集;架构:公共;所有者:邮政 -- 选择 pg_catalog.setval('activitylog_recordid_seq', 1022, true);插入到发布(参考编号,日期,联系人,总金额,银行名称, 员工姓名, trnmode, trngroup, 书签, patientid, postedon, 状态日期, 状态, 我们的银行, 支票卡详细信息, 评论, 创建, 编辑, 登录 ID, 记录 ID, 源表, 源 ID, 计数, 舍入, 放置) 值 (空, '2016-02-14 17:51:55', 'AHLCON 肠胃外药物 (印度)LTD', 232.00, '', '支票', '患者收据', 假, 0, 空, 空, "清除", ", ", ", ", "2016-02-14 17:52:03", 空, "PPPP", 59, 空, 0, 63, 空, 空); --插入 导入自 DB:00319 插入 POSTED (refnum, vdate, contact, totalamount, bankname, staffname, trnmode, trngroup, 书签, 病人ID, 发布, 状态日期, 状态, 我们的银行, 支票卡详细信息, 评论, 创建者, 编辑, 登录ID, 记录ID, 源表、源 ID、计数、舍入、放置)值(空, '2016-02-14 18:04:48', 'AHLCON PARENTERALS (INDIA) LTD', 400.00, '', '', '现金', '患者收据;', 假, 0, 空, 空, '已清除', '', '', '', '2016-02-14 18:04:50', 空, 'admin', 60, 空, 0, 64, 空, 空);插入到打印中(捐赠者姓名,参考编号,行李, 营地名称, 收据类型, 数量, 单位, 收据明细, 店员, 验证者, 验证者, 不合适, 接收日期, 不合适评论, 注释, 创建, 编辑, 登录 ID, 记录ID, Qtyissued, 数量平衡,到期,条形码,供体,条形码捐赠者,血液添加剂, 许可证引用, 源, 属性, 类别) 值('', 空, "B31399040", "C131 BLUD", "血液", 1200.0000, "毫克/毫升", "AB_Positive", 'HELLOO', 'PALS', '2015-06-30 19:03:52', 假, '2015-06-29 19:03:52', '', 空, '2015-06-30 19:05:10', '2015-07-03 12:15:33', 'PPPP', 4, 200.0000, 1000.0000, '2019-06-30 19:03:52', 空, 'd753', 空, '柠檬酸钠(二水合物)....2.63克柠檬酸 (一水合物)...0.299克葡萄糖(一水合物)...2.55克单碱 磷酸氢钠(一水合物).0.222g', '', '', 空, 空);

从文件中解析并执行 Sql 语句

您应该考虑在外部生成psql以从文件导入。您应该能够通过 stdin 将信息发送到 psql ,而不是写入磁盘上的实际文件 - 因为您提到输入数据是加密的。

可以捕获psql的输出并将其返回给用户。

解析 SQL 应由专门的解析器完成。作为 psql 的替代方法,请尝试使用可以为您执行此操作的库,例如实体框架。请参阅在 C# 中分析 SQL 代码

试试这个。如果你有一个包含一个或多个 GO 语句的查询,则必须拆分脚本以分离所有查询并逐个执行它们

var fileContent = File.ReadAllText("query.sql");
var sqlqueries = fileContent.Split(new[] {" GO "}, StringSplitOptions.RemoveEmptyEntries);
var con = new SqlConnection("connstring");
var cmd = new SqlCommand("query", con);
con.Open();
foreach (var query in sqlqueries)
{
    cmd.CommandText = query;
    cmd.ExecuteNonQuery();
}
con.Close();

这是一种黑客,但对于简单的事情(选择/插入/删除/更新)可以工作:

string pattern = "(SELECT|INSERT|DELETE|UPDATE|--)"; //ADD HERE THE SQL VERBS YOU NEED
string[] result = Regex.Split(sqls, pattern).Where(s => s != String.Empty).ToArray<string>();
for (int i = 0; i < result.Count(); i += 2) 
{
     if (!result[i].StartsWith("--"))
     {
           Console.WriteLine(result[i] + result[i + 1]);
     }
}

我相信这可以改进,但你明白了。它适用于您的示例数据

您可以尝试使用 plpgsql 命令执行脚本execute

do $$
begin
  execute 'create table t (x int); insert into t values (1), (2), (3); drop table t;'; -- Change to your script here
end $$ language plpgsql;

或为其创建存储函数:

create or replace function execute_script(in p_script text) returns void as $$
begin
  execute p_script;
end $$ language plpgsql;