【问题标题】:Error concerned with storedprocedure与存储过程有关的错误
【发布时间】:2009-04-15 11:35:09
【问题描述】:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER Procedure [dbo].[rptGGM]
(
    @FromDate datetime,
    @ToDate datetime,
    @PartyName varchar(50),
    @Type int
)

As
DECLARE @WhrStr VarChar(500)

SET @WhrStr = 
    CASE @Type
    WHEN 1 THEN
        ' And E.ATAAir between '+ @FromDate +' And '+@ToDate

    WHEN 2 THEN
        ' And D.ATASea between '+ @FromDate+ ' And '+@ToDate
    END
exec
(
'SELECT 
         A.FileNumber As [File No],
         S.POString As [PO Numbers],
         G.PartyName As [Exporter Name],
         C.CargoDesc As [Cargo Description],
         Dbo.ActualDate(A.ETA) As ETA,
         Dbo.ActualDate(IsNull(E.ATAAir, D.ATASea)) As ATA,
        S.SIString As [Supplier Invoices],
D.VesselName As [Vessel Name],
      D.VoyageNo As [Voyage No],
        dbo.PackCntDetails(A.FileID) As [Pk/Cnt Details]

FROM
    FileMain A

LEFT JOIN SIPOString S ON S.FileID=A.FileID
LEFT JOIN Party G ON G.PartyID = A.ExporterID
INNER JOIN Cargo C ON C.FileID = A.FileID
LEFT JOIN FileSea D ON D.FileID = A.FileID
LEFT JOIN FileAir E ON E.FileID = A.FileID

WHERE   
     G.PartyName='+@PartyName +' '+@WhrStr


)

在执行上述程序时,出现以下错误 消息 241,级别 16,状态 1,过程 rptGGM,第 12 行 从字符串转换日期时间时转换失败。 任何人都可以帮助解决错误。

【问题讨论】:

    标签: sql-server sql-server-2005


    【解决方案1】:

    如果没有 EXEC,这将是一个简单的查询。你为什么把这一切都包装在 EXEC 中?

    【讨论】:

      【解决方案2】:

      使用动态 SQL 是非常糟糕的做法,因为它不仅可能因为转换问题和数据长度而失败,而且还允许 SQL 注入。

      使用这样的正确查询:

      SELECT 
               A.FileNumber As [File No],
               S.POString As [PO Numbers],
               G.PartyName As [Exporter Name],
               C.CargoDesc As [Cargo Description],
               Dbo.ActualDate(A.ETA) As ETA,
               Dbo.ActualDate(IsNull(E.ATAAir, D.ATASea)) As ATA,
              S.SIString As [Supplier Invoices],
      D.VesselName As [Vessel Name],
            D.VoyageNo As [Voyage No],
              dbo.PackCntDetails(A.FileID) As [Pk/Cnt Details]
      
      FROM
          FileMain A
      
      LEFT JOIN SIPOString S ON S.FileID=A.FileID
      LEFT JOIN Party G ON G.PartyID = A.ExporterID
      INNER JOIN Cargo C ON C.FileID = A.FileID
      LEFT JOIN FileSea D ON D.FileID = A.FileID
      LEFT JOIN FileAir E ON E.FileID = A.FileID
      
      WHERE   
           G.PartyName=@PartyName AND
           (
                 ((@Type = 1) And (E.ATAAir Between @FromDate And @ToDate))
           Or
                 ((@Type = 2) And (E.ATASea Between @FromDate And @ToDate))
           )
      

      【讨论】:

        【解决方案3】:

        在构造@WhrStr 时,您需要进行从日期时间到varchar 的显式转换。以下应该有效:

        CAST(@FromDate as varchar)
        

        【讨论】:

        • Lucero - 建议将日期时间值转换为字符串究竟是如何构成提倡 SQL 注入的?
        【解决方案4】:

        您必须引用日期时间值

        ...
        WHEN 1 THEN
            ' And E.ATAAir between '''+ CAST(@FromDate AS varchar(30)) +''' And '''+CAST(@ToDate AS varchar(30)) + ''''
        
        WHEN 2 THEN
            ' And D.ATASea between '''+ CAST(@FromDate AS varchar(30))+ ' And '''+CAST(@ToDate AS varchar(30)) + ''''
        END
        ...
        

        您稍后也会在@partyname 附近遇到错误:

        ...
        WHERE   
             G.PartyName='''+@PartyName +''' '+@WhrStr
        

        编辑:添加了 CAST!

        【讨论】:

        • 还是会出现同样的错误。你能建议任何其他方式吗?在 where 条件下的语法是否有任何错误。如果是,我该如何删除它?
        • 这与你或我有什么关系?
        • 这确实令人担忧,因为人们正在 Stackoverflow 上寻找解决方案。因此,您基本上是在传播信息,导致更糟糕的 SQL 代码容易受到注入攻击。
        • @我是个女孩:没必要因为我对代码质量和安全性敏感而无礼。
        • @我是女孩,@lucero:拜托,古代历史。 Lucero确实提供了替代解决方案。
        猜你喜欢
        • 2019-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-12
        • 1970-01-01
        相关资源
        最近更新 更多