Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何在SQL Server中自动更改存储过程?_Sql Server - Fatal编程技术网

Sql server 如何在SQL Server中自动更改存储过程?

Sql server 如何在SQL Server中自动更改存储过程?,sql-server,Sql Server,我在SQL Server中有两个数据库,其中一个数据库(ConfigDb)引用另一个数据库(DataDb)。ConfigDb中的许多存储过程和函数使用DataDb中的表和函数/sp。它们的引用方式类似于[DataDb].[dbo].[u对象] 现在,我需要克隆数据库以测试版本,即从备份中将它们还原为ConfigDb\u test和DataDb\u test。显然,ConfigDb\u测试引用的是DataDb,而不是DataDb\u测试 与逐个打开SP并手动编辑相比,如何更好地处理此问题 编辑 作

我在SQL Server中有两个数据库,其中一个数据库(
ConfigDb
)引用另一个数据库(
DataDb
)。
ConfigDb
中的许多存储过程和函数使用
DataDb
中的表和函数/sp。它们的引用方式类似于
[DataDb].[dbo].[u对象]

现在,我需要克隆数据库以测试版本,即从备份中将它们还原为
ConfigDb\u test
DataDb\u test
。显然,
ConfigDb\u测试
引用的是
DataDb
,而不是
DataDb\u测试

与逐个打开SP并手动编辑相比,如何更好地处理此问题

编辑

作为参考,我把这个实用程序放在了

好的,它是用VB(不是c#)编写的——而且我不是.net的人,所以我相信有更好的方法可以做到这一点

我提醒您仔细观察代码的工作情况,但是我经常使用它,而且效果非常好

输入服务器名/凭据后,将显示数据库列表(不包括系统数据库)。选择要针对其运行的数据库(复选列表),然后输入查找/替换文本字符串。单击“开始”时,将打开/扫描每个进程,并在匹配的字符串上运行REPLACE()——因此,请小心在“查找/替换”文本框中输入的内容

就这样

请小心使用,使用风险自负

form2.vb

对象名称(按顺序)

  • cmbServer(组合框)
  • chkSSPI(复选框)
  • txtUser(文本框)
  • txtPass(文本框)
  • BTN连接(按钮)
  • 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
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
frmDBList.vb

对象名称(按顺序):

  • CLB数据库(选中列表框)
  • txtFind(文本框)
  • txtReplace(文本框)
  • lblDBName(标签)
  • lblProcNum(标签)[0]
  • lblProcCount(标签)[123]
  • lblProcName(标签)
  • btnCheckAll(按钮)
  • btnUnCheckAll(按钮)
  • btnStart(按钮)
  • btnClose(按钮)
代码隐藏:

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
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

正是因为这个原因,我尽量避免交叉引用。可能有一个“正确”的解决方案,但我会尝试使用可配置的连接字符串将进程重新工作到SSIS包中,或者使用CLR存储过程,或者获取一个新的SQL实例,这样就可以不使用数据库名称。动态SQL也是一个选项,但这是一个非常核心的解决方案。您有权访问VS/c吗?你可以编写一个应用程序来自动打开/更改每一个程序(我以前做过,我可以给你代码)。@JiggsJedi是的,我有,如果有东西可以启动就太好了with@TT是的,我最终在内部使用了SMO。基本上,它是一个简单的单用途WinForm应用程序,类似于JiggsJedi解决方案。谢谢。我也不知道SMO,谢谢!