好的,它在 VB(不是 c#)中——而且我不是 .net 人,所以我确信有更好的方法来做到这一点。
我提醒您逐步执行并观察代码的工作情况,但我经常使用它,而且效果很好!
输入服务器名称/凭据后,将出现一个数据库列表(不包括系统数据库)。选择要运行的数据库(检查列表)并输入查找/替换文本字符串。当您单击开始时,将打开/扫描每个 proc,并在匹配的字符串上运行 REPLACE() - 所以要小心您在 FIND/REPLACE 文本框中输入的内容!
来了……
请谨慎使用,使用风险自负。
form2.vb
对象名称(按顺序)
- cmbServer(组合框)
- chkSSPI(复选框)
- txtUser(文本框)
- txtPass(文本框)
- btnConnect(按钮)
- btnExit(按钮)
代码背后:
Imports System.Data.SqlClient
Public Class Form2
Public objConn As SqlConnection = New SqlConnection()
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
cmbServer.SelectedIndex = 0
chkSSPI.Checked = True
End Sub
Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
Application.Exit()
End Sub
Private Sub chkSSPI_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkSSPI.CheckedChanged
txtUser.Enabled = Not chkSSPI.Checked
txtPass.Enabled = Not chkSSPI.Checked
txtUser.Select()
End Sub
Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
If chkSSPI.Checked = False Then
objConn.ConnectionString = String.Format("Data Source={0};Initial Catalog=master;User ID={1};Password={2};", cmbServer.Text, txtUser.Text, txtPass.Text)
Else
objConn.ConnectionString = String.Format("Data Source={0}; Initial Catalog=master; Integrated Security=SSPI", cmbServer.Text)
End If
Dim frm2 As Form = New frmDBList()
Try
objConn.Open()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
Hide()
frm2.Show()
End Sub
Private Sub txtUser_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtUser.TextChanged
End Sub
End Class
frmDBList.vb
对象名称(按顺序):
- clbDatabase(选中列表框)
- txt查找(文本框)
- txtReplace(文本框)
- lblDBName(标签)
- lblProcNum(标签)[0]
- lblProcCount(标签)[123]
- lblProcName(标签)
- btnCheckAll(按钮)
- btnUnCheckAll(按钮)
- btnStart(按钮)
- btnClose(按钮)
代码背后:
Imports System.Data.SqlClient
Imports System.IO
Public Class frmDBList
Dim procText As String
Dim procList As New ArrayList
Dim errorLog As New ArrayList
Dim dbcount As Int16
Dim proccount As Int16
Dim replacecount As Int16
Dim procupdate As Boolean
Public Sub LogError(ByVal text As String, ByVal dbname As String, ByVal procname As String)
errorLog.Add("db=" + dbname + " proc=" + procname + " error=" + text)
End Sub
Public Sub SaveLog()
Dim datetime As String = Now.ToString()
datetime = Replace(datetime, "/", "")
datetime = Replace(datetime, ":", "")
Dim filename As String = "c:\procchanger_errorlog " + datetime + ".txt"
Dim objWriter As New System.IO.StreamWriter(filename)
For c As Int16 = 0 To errorLog.Count - 1
objWriter.WriteLine(errorLog(c).ToString())
Next
objWriter.Close()
End Sub
Public Sub AddListBoxItem(ByVal Item As Object, ByVal Check As Boolean)
clbDatabase.Items.Add(Item, Check)
End Sub
Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
btnStart.Enabled = False
btnClose.Enabled = False
errorLog.Clear()
dbcount = 0
proccount = 0
replacecount = 0
grpProgress.Visible = True
If clbDatabase.SelectedItems.Count = 0 Then
MsgBox("Please select at least one database to process.", vbOKOnly)
Else
For i As Integer = 0 To clbDatabase.Items.Count - 1
If clbDatabase.GetItemChecked(i) = True Then
lblDBName.Text = clbDatabase.Items(i).ToString()
dbcount += 1
procList.Clear()
GetProcList(clbDatabase.Items(i).ToString())
End If
Next
MsgBox("Complete. Replaced " + replacecount.ToString() + " occurrences, in " + proccount.ToString() + " stored procedures, across " + dbcount.ToString() + " databases.")
If errorLog.Count > 0 Then
SaveLog()
End If
grpProgress.Visible = False
For i As Integer = 0 To clbDatabase.Items.Count - 1
clbDatabase.SetItemChecked(i, CheckState.Unchecked)
Next
End If
If Form2.objConn.State = ConnectionState.Open Then Form2.objConn.Close()
btnStart.Enabled = True
btnClose.Enabled = True
End Sub
Public Sub GetProcList(ByVal dbname As String)
If Form2.objConn.State = ConnectionState.Closed Then
If Form2.chkSSPI.Checked = False Then
Form2.objConn.ConnectionString = String.Format("Data Source={0};Initial Catalog=" + dbname + ";User ID={1};Password={2};", Form2.cmbServer.Text, Form2.txtUser.Text, Form2.txtPass.Text)
Else
Form2.objConn.ConnectionString = String.Format("Data Source={0}; Initial Catalog=" + dbname + "; Integrated Security=SSPI", Form2.cmbServer.Text)
End If
Try
Form2.objConn.Open()
Catch ex As Exception
LogError(ex.Message, dbname, "")
End Try
End If
Try
Dim sqlcmd = "select name from sysobjects where xtype='P' and name not like 'dt_%'"
Using cmd As New SqlCommand(sqlcmd, Form2.objConn)
Using reader = cmd.ExecuteReader()
If reader.HasRows Then
While reader.Read()
procList.Add(reader("name").ToString())
End While
End If
End Using
End Using
Catch ex As Exception
LogError(ex.Message, dbname, "")
End Try
lblProcCount.Text = procList.Count
proccount = procList.Count
For c = 0 To procList.Count - 1
lblProcNum.Text = c.ToString()
lblProcName.Text = procList(c).ToString()
Refresh()
procupdate = False
AlterProc(dbname, procList(c).ToString())
Next
If Form2.objConn.State = ConnectionState.Open Then Form2.objConn.Close()
End Sub
Public Sub AlterProc(ByVal dbname As String, ByVal procname As String)
If Form2.objConn.State = ConnectionState.Closed Then
If Form2.chkSSPI.Checked = False Then
Form2.objConn.ConnectionString = String.Format("Data Source={0};Initial Catalog=" + dbname + ";User ID={1};Password={2};", Form2.cmbServer.Text, Form2.txtUser.Text, Form2.txtPass.Text)
Else
Form2.objConn.ConnectionString = String.Format("Data Source={0}; Initial Catalog=" + dbname + "; Integrated Security=SSPI", Form2.cmbServer.Text)
End If
Try
Form2.objConn.Open()
Catch ex As Exception
LogError(ex.Message, dbname, "")
End Try
End If
Try
Dim sqlcmd = "select * from " + dbname + ".dbo.sysobjects o inner join " + dbname + ".dbo.syscomments c on o.id = c.id where name='" + procname + "'"
Using cmd As New SqlCommand(sqlcmd, Form2.objConn)
procText = ""
Using reader = cmd.ExecuteReader()
If reader.HasRows Then
While reader.Read()
procText = procText + reader("text")
End While
End If
End Using
Dim arrProcData() = Split(procText, vbNewLine)
Dim c As Integer
procText = ""
For c = 0 To UBound(arrProcData)
If InStr(UCase(arrProcData(c)), "CREATE") > 0 And InStr(UCase(arrProcData(c)), "PROCEDURE") > 0 Then
arrProcData(c) = Replace(Replace(Replace(arrProcData(c), "CREATE", "ALTER"), "create", "alter"), "Create", "Alter")
End If
If InStr(UCase(arrProcData(c)), UCase(txtFind.Text)) > 0 Then
arrProcData(c) = Replace(UCase(arrProcData(c)), UCase(txtFind.Text), UCase(txtReplace.Text))
replacecount += 1
procupdate = True
End If
procText = procText + arrProcData(c) + vbNewLine
Next
End Using
Catch ex As Exception
LogError(ex.Message, dbname, procname)
End Try
If procupdate = True Then
Try
Dim sqlcmd = procText
Using cmd As New SqlCommand(sqlcmd, Form2.objConn)
cmd.ExecuteNonQuery()
End Using
Catch ex As Exception
LogError(ex.Message, dbname, procname)
End Try
End If
End Sub
Private Sub frmDBList_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
grpProgress.Visible = False
Try
Dim sqlcmd = "select name from master.dbo.sysdatabases where name not in ('msdb','master','temdb')"
Using cmd As New SqlCommand(sqlcmd, Form2.objConn)
Using reader = cmd.ExecuteReader()
If reader.HasRows Then
While reader.Read()
AddListBoxItem(reader("name").ToString(), CheckState.Unchecked)
End While
End If
End Using
End Using
Catch ex As Exception
LogError(ex.Message, "master", "")
End Try
Form2.objConn.Close()
End Sub
Private Sub btnClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClose.Click
Application.Exit()
End Sub
Private Sub btnCheckAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCheckAll.Click
For i As Integer = 0 To clbDatabase.Items.Count - 1
clbDatabase.SetItemChecked(i, CheckState.Checked)
Next
End Sub
Private Sub btnUnCheckAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUnCheckAll.Click
For i As Integer = 0 To clbDatabase.Items.Count - 1
clbDatabase.SetItemChecked(i, CheckState.Unchecked)
Next
End Sub
End Class