簡體   English   中英

從文件中解析並執行Sql語句

[英]Parse and execute Sql statements from file

我正在編寫SQL執行模塊,它是醫療應用程序的一部分。

模塊

  1. 接受加密的.sql文件名作為輸入。 該文件將包含dml語句,如插入行/更新行,注釋(下面的示例)
  2. 解密文件
  3. 准備一個SQL語句列表並執行,忽略注釋行(以 - 開頭的行)
  4. 如果出錯,會彈出一個亞麻布

采用的方法

  1. 加載sqlfile和descryption就可以了
    使用簡單的File.ReadAllText和預先構建的解密模塊
  2. 准備列表是模塊失敗的地方。 我用過這段代碼:

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

    它導致執行忽略由於分裂后的注釋后出現的SQL。

數據不能僅僅從換行符中拆分,因為insert語句的列值中存在換行符。 分號也是如此

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

歡迎任何有關解決方案的幫助

謝謝


編輯2: 我正在研究使用正則表達式或只是在循環中使用char解析char的可能性

SAMPLEDATA下面


- 姓名:activitylog_recordid_seq; 類型:SEQUENCE SET; 架構:公共; 所有者:postgres - SELECT pg_catalog.setval('activitylog_recordid_seq',1022,true); INSERT INTO發布(refnum,vdate,contact,totalamount,bankname,staffname,trnmode,trngroup,bookmark,patientid,poston,statusdate,status,ourbank,chequecarddetail,comment,createdon,editedon,loginid,recordid,sourcetable,sourceid,tallyid,舍入,放置)VALUES(NULL,'2016-02-14 17:51:55','AHLCON PARENTERALS(INDIA)LTD',232.00,'','','Checks','PATIENT RECEIPTS',false,0 ,NULL,NULL,'已清除','','','','2016-02-14 17:52:03',NULL,'PPPP',59,NULL,0,63,NULL,NULL); - 插入從DB:00319 INSERT INTO發布(引用文章,vdate,聯系人,totalamount,bankname,staffname,trnmode,trngroup,bookmark,patientid,postedon,statusdate,status,ourbank,chequecarddetail,comment,createdon,editedon,loginid, recordid,sourcetable,sourceid,tallyid,rounding,placed)VALUES(NULL,'2016-02-14 18:04:48','AHLCON PARENTERALS(INDIA)LTD',400.00,'','','現金', 'PATIENT RECEIPTS;',false,0,NULL,NULL,'Cleared','','','','2016-02-14 18:04:50',NULL,'admin',60,NULL, 0,64,NULL,NULL); INSERT INTO打印(donorname,referencenum,baggageid,campname,receipttype,qty,units,receiptdetail,storestaff,Verifiedby,verifiedon,isunsuitable,receiptdate,unsuitablecomment,comment,createdon,editedon,loginid,recordid,qtyissued,qtybalance,expiry,條形碼, donorref,barcodedonor,bloodadditives,licenseref,source,attributes,category)VALUES('',NULL,'B31399040','C131 BLUD','Blood',1200.0000,'mg / Ml','AB_Positive','HELLOO', 'PALS','2015-06-30 19:03:52',false,'2015-06-29 19:03:52','',NULL,'2015-06-30 19:05:10', '2015-07-03 12:15:33','PPPP',4,200.0000,1000.0000,'2019-06-30 19:03:52',NULL,'d753',NULL,'檸檬酸鈉(二水合物) .... 2.63g檸檬酸(一水合物)... 0.299g葡萄糖(一水合物)....... 2.55g一元二磷酸鈉(一水合物).0.222g','','',NULL,NULL) ;

您應該考慮從外部生成psql以從文件導入。 您應該能夠通過stdin將信息發送到psql ,而不是寫入磁盤上的實際文件 - 因為您提到輸入數據是加密的。

可以捕獲psql的輸出並將其返回給用戶。

解析SQL應該由專門的解析器完成。 作為psql的替代方法,請嘗試使用可以為您執行此操作的庫,例如Entity Framework 請參閱使用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]);
     }
}

我相信這可以改進,但你明白了。 它適用於您的示例數據

您可以嘗試使用execute plpgsql命令執行腳本:

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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM