格式化 TSQL 字符串以使用 ASP.NET 模仿 SQL 管理器的最佳方法是什么?
What is the best way to format a TSQL string to mimic SQL Manager using ASP.NET?
使用 SMO 和 ASP.NET,我正在尝试将突出显示和行格式添加到 SMO 对象(table、视图等)的脚本方法中。目前我正在使用 String.Replace 方法来匹配关键字,但这似乎并没有捕获所有的关键字。我有一个数组中的关键字,然后循环匹配 TSQL 脚本。我不确定我需要匹配哪些字符才能获取所有关键字并获取类似于 SQL Manager.
的行格式
Dim searchArr As Array = {"ADD", "EXTERNAL", "PROCEDURE", "ALL", "FETCH", "PUBLIC", "ALTER", "FILE", "RAISERROR", "AND", "FILLFACTOR", "READ", "ANY", "FOR", "READTEXT", "AS", "FOREIGN", "RECONFIGURE",
"ASC", "FREETEXT", "REFERENCES", "AUTHORIZATION", "FREETEXTTABLE", "REPLICATION", "BACKUP", "FROM", "RESTORE", "BEGIN", "FULL", "RESTRICT", "BETWEEN", "FUNCTION", "RETURN",
"BREAK", "GOTO", "REVERT", "BROWSE", "GRANT", "REVOKE", "BULK", "GROUP", "RIGHT", "BY", "HAVING", "ROLLBACK", "CASCADE", "HOLDLOCK", "ROWCOUNT", "CASE", "IDENTITY", "ROWGUIDCOL",
"CHECK", "IDENTITY_INSERT", "RULE", "CHECKPOINT", "IDENTITYCOL", "SAVE", "CLOSE", "IF", "SCHEMA", "CLUSTERED", "IN", "SECURITYAUDIT", "COALESCE", "INDEX", "SELECT",
"COLLATE", "INNER", "SEMANTICKEYPHRASETABLE", "COLUMN", "INSERT", "SEMANTICSIMILARITYDETAILSTABLE", "COMMIT", "INTERSECT", "SEMANTICSIMILARITYTABLE",
"COMPUTE", "INTO", "SESSION_USER", "CONSTRAINT", "IS", "SET", "CONTAINS", "JOIN", "SETUSER", "CONTAINSTABLE", "KEY", "SHUTDOWN", "CONTINUE", "KILL", "SOME",
"CONVERT", "LEFT", "STATISTICS", "CREATE", "LIKE", "SYSTEM_USER", "CROSS", "LINENO", "TABLE", "CURRENT", "LOAD", "TABLESAMPLE", "CURRENT_DATE", "MERGE", "TEXTSIZE",
"CURRENT_TIME", "NATIONAL", "THEN", "CURRENT_TIMESTAMP", "NOCHECK", "TO", "CURRENT_USER", "NONCLUSTERED", "TOP", "CURSOR", "NOT", "TRAN", "DATABASE", "NULL", "TRANSACTION",
"DBCC", "NULLIF", "TRIGGER", "DEALLOCATE", "OF", "TRUNCATE", "DECLARE", "OFF", "TRY_CONVERT", "DEFAULT", "OFFSETS", "TSEQUAL", "DELETE", "ON", "UNION", "DENY", "OPEN", "UNIQUE",
"DESC", "OPENDATASOURCE", "UNPIVOT", "DISK", "OPENQUERY", "UPDATE", "DISTINCT", "OPENROWSET", "UPDATETEXT", "DISTRIBUTED", "OPENXML", "USE", "DOUBLE", "OPTION", "USER",
"DROP", "Or", "VALUES", "DUMP", "ORDER", "VARYING", "ELSE", "OUTER", "VIEW", "END", "OVER", "WAITFOR", "ERRLVL", "PERCENT", "WHEN", "ESCAPE", "PIVOT", "WHERE", "EXCEPT", "PLAN", "WHILE",
"EXEC", "PRECISION", "WITH", "EXECUTE", "PRIMARY", "WITHIN GROUP", "EXISTS", "PRINT", "WRITETEXT", "EXIT", "PROC", "CREATE PROCEDURE", "NOCOUNT", "COUNT"}
Dim srv As Server
Dim name As String
Dim db As Database
Dim sp As StoredProcedure
Private Sub Admin_Props_Load(sender As Object, e As EventArgs) Handles Me.Load
openDB()
db = srv.Databases(databaseName)
If Len(Request.QueryString("name")) = 0 Then
lblData.Text = "Not a valid StoredProcedure"
Else
sp = db.StoredProcedures(Request.QueryString("name").ToString)
lblData.Text = addHighlight(sp.TextBody)
End If
End Sub
Sub openDB()
Dim sqlConn As New SqlConnection("Data Source=xxxx;Integrated Security=True;")
Dim SerCon As New Microsoft.SqlServer.Management.Common.ServerConnection(sqlConn)
srv = New Server(SerCon)
End Sub
Function addHighlight(ByVal strIn As String) As String
Dim keyWords As Array = searchArr
Dim keyInd As Integer
Dim str2() As String
str2 = strIn.Split(" ")
If Len(Trim(strIn)) > 0 And IsArray(keyWords) Then
For keyInd = LBound(keyWords) To UBound(keyWords)
For i As Integer = LBound(str2) To UBound(str2)
str2(i) = Replace(str2(i), UCase(keyWords(keyInd)), "*|*" & UCase(keyWords(keyInd)) & "*||*", 1, -1, 1)
'strIn = Replace(strIn, UCase(keyWords(keyInd)), "*|*" & UCase(keyWords(keyInd)) & "*||*", 1, -1, 1)
Next
Next
End If
strIn = Join(str2, " ")
strIn = Replace(strIn, Chr(13), "<br>", 1, -1, 1)
strIn = Replace(strIn, "*|*", "<span class=""Highlight"">")
strIn = Replace(strIn, "*||*", "</span>")
addHighlight = strIn
End Function
当我 运行 这样做时,我得到了颜色格式的混合结果,因为替换不仅会得到整个单词,还会得到更大单词的子字符串;这不应该发生。
结果应该是这样的;
CREATE PROCEDURE AddCityToList
-- Add the parameters for the stored procedure here
@idCity int,
@idProduct int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO CityProductExclude (idCity,idProduct)
VALUES (@idCity,@idProduct)
END
没有在备注中的关键字应该突出显示并大写,我怎么得到以下回复;
-- =============================================
-- AuthOR: OR,,Name>
-- CREATE date: <CREATE Date,,>
-- DESCriptiON: <DESCriptiON,,>
-- =============================================
CREATE PROCEDURE ADDCityTOLISt
-- ADD the parameters FOR the sTOred PROCEDURE here
@idCity INt,
@idProduct INt
AS
BEGIN
-- SET NOCOUNT ON ADDed TO prevent extra result SETs FROM
-- INterferINg WITH SELECT statements.
SET NOCOUNT ON;
-- INsert statements FOR PROCEDURE here
INSERT INTO CityProductExclude (idCity,idProduct)
VALUES (@idCity,@idProduct)
END
我错过了什么?任何帮助将不胜感激
考虑 sp.TextBody
是一个长字符串,包含带有换行符的存储过程命令,用空格分割可能不是区分 SQL 关键字和评论部分的好方法,因此最好根据分割从换行符出现:
str2 = strIn.Split(New String() { Environment.NewLine }, StringSplitOptions.None)
通过使用上面的赋值,它能够检测任何以 --
开头的字符串作为 SQL 注释并保持它们完整,因此使用 Regex.Replace
方法可以大写任何确切的 SQL 未标记为评论的关键词:
' Notes:
' (1) Using System.Text.RegularExpressions required to call Regex.Replace
' (2) StartsWith used to detect comment section in stored procedure body
' (3) "\b" + keyWords(keyInd) + "\b" used to replace by whole keywords only
If Len(Trim(strIn)) > 0 And IsArray(keyWords) Then
For keyInd = LBound(keyWords) To UBound(keyWords)
For i As Integer = LBound(str2) To UBound(str2)
If Not str2(i).StartsWith("--")
str2(i) = Regex.Replace(str2(i), "\b" + keyWords(keyInd) + "\b", "*|*" & UCase(keyWords(keyInd)) & "*||*", RegexOptions.IgnoreCase)
End If
Next
Next
End If
然后,将所有内容放在 addHighlight
函数中:
Function addHighlight(ByVal strIn As String) As String
Dim keyWords As Array = searchArr
Dim keyInd As Integer
Dim str2() As String
str2 = strIn.Split(New String() { Environment.NewLine }, StringSplitOptions.None)
If Len(Trim(strIn)) > 0 And IsArray(keyWords) Then
For keyInd = LBound(keyWords) To UBound(keyWords)
For i As Integer = LBound(str2) To UBound(str2)
If Not str2(i).StartsWith("--")
str2(i) = Regex.Replace(str2(i), "\b" + keyWords(keyInd) + "\b", "*|*" & UCase(keyWords(keyInd)) & "*||*", RegexOptions.IgnoreCase)
End If
Next
Next
End If
strIn = Join(str2, Environment.NewLine)
strIn = Replace(strIn, Chr(13), "<br />", 1, -1, 1)
strIn = Replace(strIn, "*|*", "<span class=""Highlight"">")
strIn = Replace(strIn, "*||*", "</span>")
addHighlight = strIn
End Function
注意:要使这个技巧起作用,请设置 strIn
内容以在注释符号前包含换行符,如下所示(仅当 T-SQL 字符串在注释前不包含换行符时使用):
If Not strIn.Contains(Environment.NewLine) Then
strIn = Replace(strIn, "--", Environment.NewLine & "--")
End If
相关:
Way to have String.Replace only hit "whole words"
使用 SMO 和 ASP.NET,我正在尝试将突出显示和行格式添加到 SMO 对象(table、视图等)的脚本方法中。目前我正在使用 String.Replace 方法来匹配关键字,但这似乎并没有捕获所有的关键字。我有一个数组中的关键字,然后循环匹配 TSQL 脚本。我不确定我需要匹配哪些字符才能获取所有关键字并获取类似于 SQL Manager.
的行格式 Dim searchArr As Array = {"ADD", "EXTERNAL", "PROCEDURE", "ALL", "FETCH", "PUBLIC", "ALTER", "FILE", "RAISERROR", "AND", "FILLFACTOR", "READ", "ANY", "FOR", "READTEXT", "AS", "FOREIGN", "RECONFIGURE",
"ASC", "FREETEXT", "REFERENCES", "AUTHORIZATION", "FREETEXTTABLE", "REPLICATION", "BACKUP", "FROM", "RESTORE", "BEGIN", "FULL", "RESTRICT", "BETWEEN", "FUNCTION", "RETURN",
"BREAK", "GOTO", "REVERT", "BROWSE", "GRANT", "REVOKE", "BULK", "GROUP", "RIGHT", "BY", "HAVING", "ROLLBACK", "CASCADE", "HOLDLOCK", "ROWCOUNT", "CASE", "IDENTITY", "ROWGUIDCOL",
"CHECK", "IDENTITY_INSERT", "RULE", "CHECKPOINT", "IDENTITYCOL", "SAVE", "CLOSE", "IF", "SCHEMA", "CLUSTERED", "IN", "SECURITYAUDIT", "COALESCE", "INDEX", "SELECT",
"COLLATE", "INNER", "SEMANTICKEYPHRASETABLE", "COLUMN", "INSERT", "SEMANTICSIMILARITYDETAILSTABLE", "COMMIT", "INTERSECT", "SEMANTICSIMILARITYTABLE",
"COMPUTE", "INTO", "SESSION_USER", "CONSTRAINT", "IS", "SET", "CONTAINS", "JOIN", "SETUSER", "CONTAINSTABLE", "KEY", "SHUTDOWN", "CONTINUE", "KILL", "SOME",
"CONVERT", "LEFT", "STATISTICS", "CREATE", "LIKE", "SYSTEM_USER", "CROSS", "LINENO", "TABLE", "CURRENT", "LOAD", "TABLESAMPLE", "CURRENT_DATE", "MERGE", "TEXTSIZE",
"CURRENT_TIME", "NATIONAL", "THEN", "CURRENT_TIMESTAMP", "NOCHECK", "TO", "CURRENT_USER", "NONCLUSTERED", "TOP", "CURSOR", "NOT", "TRAN", "DATABASE", "NULL", "TRANSACTION",
"DBCC", "NULLIF", "TRIGGER", "DEALLOCATE", "OF", "TRUNCATE", "DECLARE", "OFF", "TRY_CONVERT", "DEFAULT", "OFFSETS", "TSEQUAL", "DELETE", "ON", "UNION", "DENY", "OPEN", "UNIQUE",
"DESC", "OPENDATASOURCE", "UNPIVOT", "DISK", "OPENQUERY", "UPDATE", "DISTINCT", "OPENROWSET", "UPDATETEXT", "DISTRIBUTED", "OPENXML", "USE", "DOUBLE", "OPTION", "USER",
"DROP", "Or", "VALUES", "DUMP", "ORDER", "VARYING", "ELSE", "OUTER", "VIEW", "END", "OVER", "WAITFOR", "ERRLVL", "PERCENT", "WHEN", "ESCAPE", "PIVOT", "WHERE", "EXCEPT", "PLAN", "WHILE",
"EXEC", "PRECISION", "WITH", "EXECUTE", "PRIMARY", "WITHIN GROUP", "EXISTS", "PRINT", "WRITETEXT", "EXIT", "PROC", "CREATE PROCEDURE", "NOCOUNT", "COUNT"}
Dim srv As Server
Dim name As String
Dim db As Database
Dim sp As StoredProcedure
Private Sub Admin_Props_Load(sender As Object, e As EventArgs) Handles Me.Load
openDB()
db = srv.Databases(databaseName)
If Len(Request.QueryString("name")) = 0 Then
lblData.Text = "Not a valid StoredProcedure"
Else
sp = db.StoredProcedures(Request.QueryString("name").ToString)
lblData.Text = addHighlight(sp.TextBody)
End If
End Sub
Sub openDB()
Dim sqlConn As New SqlConnection("Data Source=xxxx;Integrated Security=True;")
Dim SerCon As New Microsoft.SqlServer.Management.Common.ServerConnection(sqlConn)
srv = New Server(SerCon)
End Sub
Function addHighlight(ByVal strIn As String) As String
Dim keyWords As Array = searchArr
Dim keyInd As Integer
Dim str2() As String
str2 = strIn.Split(" ")
If Len(Trim(strIn)) > 0 And IsArray(keyWords) Then
For keyInd = LBound(keyWords) To UBound(keyWords)
For i As Integer = LBound(str2) To UBound(str2)
str2(i) = Replace(str2(i), UCase(keyWords(keyInd)), "*|*" & UCase(keyWords(keyInd)) & "*||*", 1, -1, 1)
'strIn = Replace(strIn, UCase(keyWords(keyInd)), "*|*" & UCase(keyWords(keyInd)) & "*||*", 1, -1, 1)
Next
Next
End If
strIn = Join(str2, " ")
strIn = Replace(strIn, Chr(13), "<br>", 1, -1, 1)
strIn = Replace(strIn, "*|*", "<span class=""Highlight"">")
strIn = Replace(strIn, "*||*", "</span>")
addHighlight = strIn
End Function
当我 运行 这样做时,我得到了颜色格式的混合结果,因为替换不仅会得到整个单词,还会得到更大单词的子字符串;这不应该发生。 结果应该是这样的;
CREATE PROCEDURE AddCityToList
-- Add the parameters for the stored procedure here
@idCity int,
@idProduct int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO CityProductExclude (idCity,idProduct)
VALUES (@idCity,@idProduct)
END
没有在备注中的关键字应该突出显示并大写,我怎么得到以下回复;
-- =============================================
-- AuthOR: OR,,Name>
-- CREATE date: <CREATE Date,,>
-- DESCriptiON: <DESCriptiON,,>
-- =============================================
CREATE PROCEDURE ADDCityTOLISt
-- ADD the parameters FOR the sTOred PROCEDURE here
@idCity INt,
@idProduct INt
AS
BEGIN
-- SET NOCOUNT ON ADDed TO prevent extra result SETs FROM
-- INterferINg WITH SELECT statements.
SET NOCOUNT ON;
-- INsert statements FOR PROCEDURE here
INSERT INTO CityProductExclude (idCity,idProduct)
VALUES (@idCity,@idProduct)
END
我错过了什么?任何帮助将不胜感激
考虑 sp.TextBody
是一个长字符串,包含带有换行符的存储过程命令,用空格分割可能不是区分 SQL 关键字和评论部分的好方法,因此最好根据分割从换行符出现:
str2 = strIn.Split(New String() { Environment.NewLine }, StringSplitOptions.None)
通过使用上面的赋值,它能够检测任何以 --
开头的字符串作为 SQL 注释并保持它们完整,因此使用 Regex.Replace
方法可以大写任何确切的 SQL 未标记为评论的关键词:
' Notes:
' (1) Using System.Text.RegularExpressions required to call Regex.Replace
' (2) StartsWith used to detect comment section in stored procedure body
' (3) "\b" + keyWords(keyInd) + "\b" used to replace by whole keywords only
If Len(Trim(strIn)) > 0 And IsArray(keyWords) Then
For keyInd = LBound(keyWords) To UBound(keyWords)
For i As Integer = LBound(str2) To UBound(str2)
If Not str2(i).StartsWith("--")
str2(i) = Regex.Replace(str2(i), "\b" + keyWords(keyInd) + "\b", "*|*" & UCase(keyWords(keyInd)) & "*||*", RegexOptions.IgnoreCase)
End If
Next
Next
End If
然后,将所有内容放在 addHighlight
函数中:
Function addHighlight(ByVal strIn As String) As String
Dim keyWords As Array = searchArr
Dim keyInd As Integer
Dim str2() As String
str2 = strIn.Split(New String() { Environment.NewLine }, StringSplitOptions.None)
If Len(Trim(strIn)) > 0 And IsArray(keyWords) Then
For keyInd = LBound(keyWords) To UBound(keyWords)
For i As Integer = LBound(str2) To UBound(str2)
If Not str2(i).StartsWith("--")
str2(i) = Regex.Replace(str2(i), "\b" + keyWords(keyInd) + "\b", "*|*" & UCase(keyWords(keyInd)) & "*||*", RegexOptions.IgnoreCase)
End If
Next
Next
End If
strIn = Join(str2, Environment.NewLine)
strIn = Replace(strIn, Chr(13), "<br />", 1, -1, 1)
strIn = Replace(strIn, "*|*", "<span class=""Highlight"">")
strIn = Replace(strIn, "*||*", "</span>")
addHighlight = strIn
End Function
注意:要使这个技巧起作用,请设置 strIn
内容以在注释符号前包含换行符,如下所示(仅当 T-SQL 字符串在注释前不包含换行符时使用):
If Not strIn.Contains(Environment.NewLine) Then
strIn = Replace(strIn, "--", Environment.NewLine & "--")
End If
相关:
Way to have String.Replace only hit "whole words"