如果查询失败,如何从在 cmd 中执行的文本文件中回滚已执行的查询?

How to rollback executed queries from text file executed in cmd if query failed?

我有一个程序可以导出包含查询 insertdelete 查询) 的文本文件,然后需要将其导入到具有不同数据库连接的相同程序(如备份和恢复).

我已经成功创建了一个功能来导出和导入在 cmd 中运行查询的文本文件。我的问题是,如果在执行过程中失败,如何回滚已执行的查询?

如果在 vb.net 代码中执行,我知道如何做 COMMIT-TRANSACTION-AND ROLLBACK,但在命令提示符中执行时我不知道该怎么做。

这是我的文本文件中的示例数据:

DELETE FROM io_generated WHERE (`id`='220401-00001-015' AND employee_id=1) OR (`id`='220402-00001-015' AND employee_id=1) OR (`id`='220404-00001-015' AND employee_id=1) OR (`id`='220405-00001-015' AND employee_id=1);
INSERT INTO io_generated(`id`, `employee_id`, `date`, `branch_id`, `in1`, `out1`, `in2`, `out2`, `in3`, `out3`, `in4`, `out4`, `branch1`, `branch2`, `branch3`, `branch4`, `branch5`, `branch6`, `branch7`, `branch8`, `in1_edited`, `out1_edited`, `in2_edited`, `out2_edited`, `in3_edited`, `out3_edited`, `in4_edited`, `out4_edited`, `late1`, `late2`, `late3`, `late4`, `hrs1`, `hrs2`, `ot_hrs`, `ut1`, `ut2`, `ut3`, `ut4`, `day_count`, `date_generated`, `generated_by`, `is_edited`, `edited_by`, `last_date_edited`, `uploaded`, `upload_date`, `verified`) VALUES('220401-00001-015', 1, '2022-04-01', 15, "2022-04-01 07:46:03", NULL, NULL, "2022-04-01 12:03:23", "2022-04-01 12:49:16", NULL, NULL, "2022-04-01 17:27:26", 15, NULL, NULL, 15, 15, NULL, NULL, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 1, "2022-04-29 09:51:20", 599, 0, NULL, NULL, 2, NOW(), 0),('220402-00001-015', 1, '2022-04-02', 15, "2022-04-02 07:37:35", NULL, NULL, "2022-04-02 12:09:03", "2022-04-02 12:50:25", NULL, NULL, "2022-04-02 17:01:24", 15, NULL, NULL, 15, 15, NULL, NULL, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 1, "2022-04-29 09:51:21", 599, 0, NULL, NULL, 2, NOW(), 0),('220404-00001-015', 1, '2022-04-04', 15, "2022-04-04 09:02:25", NULL, NULL, "2022-04-04 12:05:04", "2022-04-04 12:49:17", NULL, NULL, "2022-04-04 17:02:59", 15, NULL, NULL, 15, 15, NULL, NULL, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.97, 4, 0, 1.03, 0, 0, 0, 1, "2022-04-29 09:51:22", 599, 0, NULL, NULL, 2, NOW(), 0),('220405-00001-015', 1, '2022-04-05', 15, "2022-04-05 07:53:10", NULL, NULL, "2022-04-05 12:05:39", "2022-04-05 12:56:48", NULL, NULL, "2022-04-05 17:01:25", 15, NULL, NULL, 15, 15, NULL, NULL, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 1, "2022-04-29 09:51:23", 599, 0, NULL, NULL, 2, NOW(), 0);
INSERT INTO io_official(`id`, `employee_id`, `date`, `branch_id`, `log`, `type`, `uploaded`, `upload_date`) VALUES('220401-074603-00001', 1, '2022-04-01', 15, '2022-04-01 07:46:03', 'In', 2, NOW()),('220401-120323-00001', 1, '2022-04-01', 15, '2022-04-01 12:03:23', 'Out', 2, NOW()),('220401-124916-00001', 1, '2022-04-01', 15, '2022-04-01 12:49:16', 'In', 2, NOW()),('220401-172726-00001', 1, '2022-04-01', 15, '2022-04-01 17:27:26', 'Out', 2, NOW()),('220402-073735-00001', 1, '2022-04-02', 15, '2022-04-02 07:37:35', 'In', 2, NOW()),('220402-120903-00001', 1, '2022-04-02', 15, '2022-04-02 12:09:03', 'Out', 2, NOW()),('220402-125025-00001', 1, '2022-04-02', 15, '2022-04-02 12:50:25', 'In', 2, NOW()),('220402-170124-00001', 1, '2022-04-02', 15, '2022-04-02 17:01:24', 'Out', 2, NOW()),('220404-090225-00001', 1, '2022-04-04', 15, '2022-04-04 09:02:25', 'In', 2, NOW()),('220404-120504-00001', 1, '2022-04-04', 15, '2022-04-04 12:05:04', 'Out', 2, NOW()),('220404-124917-00001', 1, '2022-04-04', 15, '2022-04-04 12:49:17', 'In', 2, NOW()),('220404-170259-00001', 1, '2022-04-04', 15, '2022-04-04 17:02:59', 'Out', 2, NOW()),('220405-075310-00001', 1, '2022-04-05', 15, '2022-04-05 07:53:10', 'In', 2, NOW()),('220405-120539-00001', 1, '2022-04-05', 15, '2022-04-05 12:05:39', 'Out', 2, NOW()),('220405-125648-00001', 1, '2022-04-05', 15, '2022-04-05 12:56:48', 'In', 2, NOW()),('220405-170125-00001', 1, '2022-04-05', 15, '2022-04-05 17:01:25', 'Out', 2, NOW());
INSERT INTO io_unofficial(`id`, `employee_id`, `date`, `branch_id`, `log`, `type`, `remarks`, `uploaded`, `upload_date`) VALUES('220404-142625-00001', 1, '2022-04-04', 15, '2022-04-04 14:26:25', 'Out', "online payment at SM Pili", 2, NOW()),('220404-144509-00001', 1, '2022-04-04', 15, '2022-04-04 14:45:09', 'In', NULL, 2, NOW());

如果文本文件查询是逐行的,我可以使用这段代码,如果失败我可以回滚事务:

直接使用ReadLine执行

Dim conn As New MySqlConnection(AMSLocalCS)
Try
    For Each updateFile As String In openFileDialog1.FileNames
        conn.Open()
        DB.START_TRANSACTION(conn)
        While (reader.Peek() <> -1)
            line = reader.ReadLine()
            If line.StartsWith("<item key=""") Then
                Dim Firstpart As String = Nothing
                Firstpart = line.Substring(11, line.IndexOf(""" value=") - 11)
                Debug.WriteLine(Firstpart)
                lines = lines + 1
                Application.DoEvents()
            Else
                command = New MySqlCommand(line, conn)
                command.ExecuteNonQuery()
                Application.DoEvents()
            End If
        End While
        reader.Close()
        DB.COMMIT(conn)
        System.IO.File.Delete(updateFile)
    Next
    MsgBox("Update Complete!", MsgBoxStyle.Information, "Updated")
Catch ex As MySqlException
    DB.ROLLBACK(conn)
Catch ex As Exception
    DB.ROLLBACK(conn)
Finally
    conn.Close()
End Try

但问题是,有时文本文件包含 enterline-feed,这会使查询不符合要求。所以我决定在命令提示符下直接执行查询的地方使用这段代码,这是一个有效的代码,但如果失败我不知道如何回滚:

在cmd中执行文本文件

Dim myProcess As New Process()
myProcess.StartInfo.FileName = "cmd.exe"
myProcess.StartInfo.UseShellExecute = False
myProcess.StartInfo.WorkingDirectory = mysql_directory
myProcess.StartInfo.RedirectStandardInput = True
myProcess.StartInfo.RedirectStandardOutput = True
myProcess.Start()
Dim myStreamWriter As StreamWriter = myProcess.StandardInput
Dim mystreamreader As StreamReader = myProcess.StandardOutput

myStreamWriter.WriteLine("mysql -u " & My.Settings.amsLocalUid & " --password=" & My.Settings.amsLocalPwd & " -h " & My.Settings.amsLocalServer & " """ & My.Settings.amsLocalDatabase & """ < """ + file + """ ")
myStreamWriter.Close()
myProcess.WaitForExit()
myProcess.Close()
MsgBox(filetype & " File Imported Successfully!", MsgBoxStyle.Information, "Imported")
System.IO.File.Delete(file)

有没有办法让我检查查询是否在命令提示符下执行失败并在失败后回滚?

所以,这就是我所做的,根据@danblack 的建议,我应该继续读取文件并直接在 vb.net 代码中执行它们,而不是使用 cmd。这是我所做的,我没有逐行读取文本文件的行,而是使用了 File.ReadAllText() 函数,因此我可以使用 Try Catch.

轻松检测查询是否失败

代码片段

.....
Try
    For Each updateFile As String In openFileDialog1.FileNames
        conn.Open()
        DB.START_TRANSACTION(conn)
        Dim script As String
        script = File.ReadAllText(updateFile) ' use this insead of .ReadLine

        Using cmd As New MySqlCommand(script, conn)
            cmd.ExecuteNonQuery()
        End Using

        DB.COMMIT(conn)
        System.IO.File.Delete(updateFile)
    Next
    MsgBox("Update Complete!", MsgBoxStyle.Information, "Updated")
Catch ex As MySqlException
    DB.ROLLBACK(conn)
Catch ex As Exception
    DB.ROLLBACK(conn)
Finally
    conn.Close()
End Try
.....