【问题标题】:Change stored proc to inline sql将存储过程更改为内联 sql
【发布时间】:2016-03-23 04:41:16
【问题描述】:

我有以下经典的 asp 工作,调用数据库中的存储过程。我想把它转换过来,而不是调用它在 sql 中传递的存储过程,添加婴儿车然后执行它。

我尝试了各种方法,但都无法正常工作。 有人可以转换这个例子吗?

在使用参数传递 sql 时似乎很难得到合理的错误消息。有没有办法查看此调用的痕迹,以便我们了解导致问题的原因?

Set cmd = server.createobject("ADODB.Command")
cmd.ActiveConnection = theDatabase
cmd.CommandType = adCmdStoredProc
cmd.commandText = "AddResponse"

cmd.Parameters("@id") = id
cmd.Parameters("@pc") = pc
cmd.Parameters("@idDate") = now

cmd.Execute , , adExecuteNoRecords
set cmd = Nothing

存储过程定义

ALTER PROCEDURE [dbo].[AddResponse] @id NVARCHAR(12), @pc NVARCHAR(12), @idDate  datetime
AS
BEGIN
    SET NOCOUNT ON;
    select * from EmailResponse 
    if not exists (SELECT id, projectCode FROM EmailResponse WHERE id = @id and projectCode = @pc)
    begin 
        INSERT INTO EmailResponse (id, projectCode, dateEntered) VALUEs(@id, @pc, @idDate) 
    end
END

编辑:
这是我给大家的答案。
哇,stackoverflow 很棒,因为每个人都和自己一样
花一点时间帮助别人的人。

选择 * 是一个错误

我必须维护一些旧的 asp 代码并将其转换为使用存储过程。
存储过程是“大多数”时间的方式。
由于各种原因,有时最好在代码中包含 sql。
(快速测试开发,无法访问数据库等)
所以我需要知道如何处理这两种方式。

cmd.Parameters.Refresh
如果没有这个调用,我的代码可以正常工作。
真的有必要吗?
阅读它应该做什么对我为什么需要使用它没有多大帮助

了解类型对于所有类型的编程都至关重要。
这正是我所要求的以及更多。
Carl Prothman - 数据类型映射
谢谢你!

我也想知道如何设置记录集对象,即使我忘了问。也谢谢你!
设置 rs = server.createObject ("adodb.recordset")
rs =- cmd.Execute

我得到了所有三个工作。 对于任何对此感兴趣的人来说,正在工作和测试代码以显示所有三种方法。

' Stored proc example
' ------------------------------------------
dim theDatabase, cmd, id, pc
theDatabase    = "Driver={SQL Server}; Server=10.10.10.10,1433; Database=Test; uid=TestUser; pwd=TestPass;"

id = cleanInt(request.querystring("id"))
pc = sqlSafe(clean(request.querystring("pc")))

if pc<>"" and id<>"" then
    Set cmd = server.createobject("ADODB.Command")

    cmd.ActiveConnection = theDatabase
    cmd.CommandType      = adCmdStoredProc
    cmd.commandText      = "AddResponse"

    cmd.Parameters("@id")     = id
    cmd.Parameters("@pc")     = pc
    cmd.Parameters("@idDate") = now

    cmd.Execute , , adExecuteNoRecords
    set cmd = Nothing
end if


' Inline SQl with ? example
' ------------------------------------------
dim theDatabase, cmd, id, pc
theDatabase    = "Driver={SQL Server}; Server=10.10.10.10,1433; Database=Test; uid=TestUser; pwd=TestPass;"

id = cleanInt(request.querystring("id"))
pc = sqlSafe(clean(request.querystring("pc")))

if pc<>"" and id<>"" then
    Set cmd = server.createobject("ADODB.Command")

    cmd.ActiveConnection = theDatabase
    cmd.CommandType      = adCmdText
    cmd.CommandText      = _
        "if not exists (SELECT id, projectCode FROM EmailResponse WHERE id = ? and projectCode = ?)" &_
        "begin INSERT INTO EmailResponse (id, projectCode, dateEntered) VALUEs(?, ?, ?) end "

    cmd.Parameters.Append cmd.CreateParameter("@id",     adInteger,     adParamInput,   ,  id)
    cmd.Parameters.Append cmd.CreateParameter("@pc",     adVarchar,     adParamInput, 12,  pc)
    cmd.Parameters.Append cmd.CreateParameter("@id2",    adInteger,     adParamInput,   ,  id)
    cmd.Parameters.Append cmd.CreateParameter("@pc2",    adVarchar,     adParamInput, 12,  pc)        
    cmd.Parameters.Append cmd.CreateParameter("@idDate", adDBTimeStamp, adParamInput, -1,  now)

    cmd.Execute , , adExecuteNoRecords
    set cmd = Nothing
end if

' Inline SQl with @ example
' ------------------------------------------
dim theDatabase, cmd, sql, id, pc
theDatabase    = "Driver={SQL Server}; Server=10.10.10.10,1433; Database=Test; uid=TestUser; pwd=TestPass;"

id = cleanInt(request.querystring("id"))
pc = sqlSafe(clean(request.querystring("pc")))

if pc<>"" and id<>"" then
    Set cmd = server.createobject("ADODB.Command")

    sql = ""
    sql = sql & "SET NOCOUNT ON;" & vbCrLf
    sql = sql & "DECLARE @id NVARCHAR(12)" & vbCrLf
    sql = sql & "DECLARE @pc NVARCHAR(12)" & vbCrLf
    sql = sql & "DECLARE @idDate DATETIME" & vbCrLf
    sql = sql & "SELECT @id = ?, @pc = ?, @idDate = ?" & vbCrLf
    sql = sql & "IF NOT EXISTS (SELECT id, projectCode FROM EmailResponse WHERE id = @id and projectCode = @pc)" & vbCrLf
    sql = sql & "INSERT INTO EmailResponse (id, projectCode, dateEntered) VALUEs(@id, @pc, @idDate);"

    cmd.ActiveConnection = theDatabase
    cmd.CommandType      = adCmdText
    cmd.CommandText      = sql
    cmd.Prepared = true
    cmd.Parameters.Append cmd.CreateParameter("@id",     adInteger,     adParamInput,   ,  id)
    cmd.Parameters.Append cmd.CreateParameter("@pc",     adVarchar,     adParamInput, 12,  pc)
    cmd.Parameters.Append cmd.CreateParameter("@idDate", adDBTimeStamp, adParamInput, -1,  now)

    cmd.Execute , , adExecuteNoRecords
    set cmd = Nothing
end if

谢谢大家。

【问题讨论】:

  • 为什么要切换到动态SQL而不是存储过程?,你的代码很好,你只是missing one line
  • 我会支持 Lankymart,在这里,奥斯汀;没有理由改变。
  • @Austin 你觉得有什么建议有帮助吗?
  • 在大家的帮助下,我得到了所有三种方法,并创建了工作示例。请参阅对我的原始帖子的编辑。大家交流

标签: stored-procedures vbscript asp-classic


【解决方案1】:

在尝试设置命名参数值之前,使用Parameters 集合的Refresh() method 缺少上述代码没有任何问题。

Set cmd = server.createobject("ADODB.Command")
With
  .ActiveConnection = theDatabase
  .CommandType = adCmdStoredProc
  .commandText = "AddResponse"

  'Query the provider for the parameter details
  Call .Parameters.Refresh()

  .Parameters("@id") = id
  .Parameters("@pc") = pc
  .Parameters("@idDate") = now

  Call .Execute(, , adExecuteNoRecords)
End With
set cmd = Nothing

如果您不想使用此方法,则参数定义必须来自某个地方,因此另一种选择是自己定义它们以反映存储过程的定义。

Set cmd = server.createobject("ADODB.Command")
With cmd
  .ActiveConnection = theDatabase
  .CommandType = adCmdStoredProc
  .commandText = "AddResponse"

  'Define parameters manually
  Call .Parameters.Append(.CreateParameter("@id", adVarWChar, adParamInput, 12))
  Call .Parameters.Append(.CreateParameter("@pc", adVarWChar, adParamInput, 12))
  Call .Parameters.Append(.CreateParameter("@idDate", adDBTimeStamp, adParamInput, 8))

  .Parameters("@id") = id
  .Parameters("@pc") = pc
  .Parameters("@idDate") = now

  Call .Execute(, , adExecuteNoRecords)
End With
set cmd = Nothing

如果您确实按照手动路线进行操作,这是一个很好的资源来确定要使用的 ADO DataTypeEnum 常量是 Carl Prothman - Data Type Mapping

旁注:您的存储过程中有这一行;

select * from EmailResponse 

希望返回结果集,但您在 ADODB.Command Execute() 方法中指定 adExecuteNoRecords 会导致此被忽略,如果您确实想返回它,请调整以上内容;

Dim rs
...
With cmd
  ...
  Set rs = .Execute()
End With

... 用于显示代码被省略的地方


需要指出,虽然 @dimason approach (因为已删除,不知道为什么...) 是合理的,但在不需要时添加两个额外参数会使事情变得过于复杂,您可以只在动态 SQL 中声明参数并分配它们以使用那些本地声明的变量来运行语句。

Dim sql

sql = ""
sql = sql & "SET NOCOUNT ON;" & vbCrLf
sql = sql & "DECLARE @id NVARCHAR(12)" & vbCrLf
sql = sql & "DECLARE @pc NVARCHAR(12)" & vbCrLf
sql = sql & "DECLARE @idDate DATETIME" & vbCrLf
sql = sql & "SELECT @id = ?, @pc = ?, @idDate = ?" & vbCrLf
sql = sql & "SELECT * FROM EmailResponse;" & vbCrLf
sql = sql & "IF NOT EXISTS (SELECT id, projectCode FROM EmailResponse WHERE id = @id and projectCode = @pc)" & vbCrLf
sql = sql & "INSERT INTO EmailResponse (id, projectCode, dateEntered) VALUEs(@id, @pc, @idDate);"

Set cmd = server.createobject("ADODB.Command")
With cmd
  .ActiveConnection = theDatabase
  .CommandType = adCmdText
  .CommandText = sql
  .Prepared = true
  .Parameters.Append cmd.CreateParameter("@id", adVarChar, adParamInput, 12, id)
  .Parameters.Append cmd.CreateParameter("@pc", adVarChar, adParamInput, 12, pc)
  .Parameters.Append cmd.CreateParameter("@idDate", adDBTimeStamp,  adParamInput, 8, Now())
  Set rsOut = .Execute()
End With
Set cmd = Nothing

有用的链接

【讨论】:

    【解决方案2】:

    要从存储过程切换到内联 SQL,需要进行更改

    cmd.CommandType = adCmdStoredProc
    

    cmd.CommandType = adCmdText
    

    然后你需要将查询添加到命令文本属性中:

    cmd.CommandText = "SELECT * FROM Orders WHERE CustomerID = ?"
    

    以上行来自 MSDN 上的Command Object Parameters example

    【讨论】:

    • 这也可以,但是为什么要在存储过程正常工作时切换到动态 SQL 呢?
    猜你喜欢
    • 2014-08-29
    • 2012-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多