【问题标题】:OLEDB query to SQL Server fails对 SQL Server 的 OLEDB 查询失败
【发布时间】:2011-09-26 23:29:46
【问题描述】:

我有两个 SQL 查询:

一个。

SELECT (upper(rtrim(ltrim(lastname))) + upper(rtrim(ltrim(firstname))) + 
     upper(rtrim(ltrim(middlename))) + rtrim(ltrim(v)) ) AS userCompareStr 
FROM atable ;

乙。

SELECT (upper(rtrim(ltrim(lastname))) + upper(rtrim(ltrim(firstname))) + 
      upper(rtrim(ltrim(middlename))) + rtrim(ltrim(v)) ) AS userCompareStr 
 FROM atable  WHERE userCompareStr='GAPYLE1111' ;

我有以下代码:

    Dim sql As String
    Dim conn As OleDbConnection
    Dim cmd As OleDbDataAdapter
    Dim ds As DataSet
    Dim tbl As DataTable

    conn = " something here "
    cmd = New OleDbDataAdapter(sql, conn)
    ds = New DataSet
    cmd.Fill(ds)
    tbl = New DataTable
    tbl = ds.Tables(0)

据我所知,当 sql 设置为字符串 A 时它似乎可以工作,但当它设置为字符串 B 时则不行。

这让我怀疑该子句有问题 WHERE userCompareStr='GAPYLE1111'

我不能以这种方式使用别名 userCompareStr 吗?我找不到这种用法的任何例子,但是当别名用于表名时,我确实找到了类似的用法——而且我没有看到任何反对我们这种用法的地方。

【问题讨论】:

    标签: asp.net sql-server select oledb alias


    【解决方案1】:

    您有三个选择。

    1) 重复你在 where 的选择中所做的事情

    SELECT (upper(rtrim(ltrim(lastname))) + upper(rtrim(ltrim(firstname))) + 
          upper(rtrim(ltrim(middlename))) + rtrim(ltrim(v)) ) AS userCompareStr 
    FROM atable  
    
    WHERE  (upper(rtrim(ltrim(lastname))) + upper(rtrim(ltrim(firstname))) + 
          upper(rtrim(ltrim(middlename))) + rtrim(ltrim(v)) ) ='GAPYLE1111' ;
    

    2) 使用公用表表达式

    with CTE AS 
    (SELECT (upper(rtrim(ltrim(lastname))) + upper(rtrim(ltrim(firstname))) + 
          upper(rtrim(ltrim(middlename))) + rtrim(ltrim(v)) ) AS userCompareStr 
    FROM atable  )
    SELECT userCompareStr FROM CTE where userCompareStr = 'GAPYLE1111';
    

    3) 内联查询见 Maziar Taheri 的回答

    顺便说一句,我希望“GAPYLE1111”不是来自用户输入,否则您将面临 SQL 注入攻击。改用参数化查询

    【讨论】:

    • 这对我来说都是新闻。感谢您提供额外的指针。我会调查的。
    • @TheFallibleFiend 没问题,这是关于该主题的经典漫画xkcd.com/327
    • 在我看来 OLEDB 不喜欢“与”。我已经简化了 sql,希望它不会返回任何结果,但至少要执行: WITH cte AS (SELECT (lastname + firstname + middlename + ssn4) as userCompareStr FROM atable ) SELECT userCompareStr FROM cte WHERE userCompareStr='GAPYLE1111';尽管如此,它还是失败了。我不确定,但我认为 oledb 不能识别所有 sql。我将尝试其他一些示例。
    • @TheFallibleFiend 我忘了说这适用于 SQL 2005 及更高版本,您使用的是 SQL 2000 吗?
    • 康拉德,这是 Microsoft SQL Server 2008。
    【解决方案2】:

    不,您不能在 WHERE 子句中使用别名列。

    Using an Alias column in the where clause in ms-sql 2000

    (这篇文章是关于 SQL 2000,但今天仍然适用)

    【讨论】:

      【解决方案3】:

      您不能在 where 子句中使用您在 select 子句中设置的别名。

      试试这个:

      SELECT * FROM
      (
      SELECT (upper(rtrim(ltrim(lastname))) + upper(rtrim(ltrim(firstname))) + upper(rtrim(ltrim(middlename))) + rtrim(ltrim(v)) ) AS userCompareStr FROM atable)
      as nested
      WHERE userCompareStr='GAPYLE1111' ;
      

      【讨论】:

        【解决方案4】:

        我暂时离开了这个问题,做了一些别的事情,然后又回来了。 我通过从使用 oledb 切换到“其他东西”解决了主要问题。 我不确定新的(对我而言)方法叫什么——除了“本机 sqlserver?”

        要点:

        1. 不能在 WHERE 子句中使用字段名称别名。 (根据 maziar 和 matt)

        2. Conrad 的修复 #1 适用于 OLEDB,但我不喜欢这种方法,因为它很冗长(实际命令比我在此处提供的缩小示例复杂得多)并且有很多不同的调用。容易出错且难以阅读(但在紧要关头工作)。

        3. 要获得 WITH 或嵌套选择工作,我必须从 OLEDB 切换到“本机 sqlserver”(或其他任何名称)。 WITH(由康拉德建议)是我的首选解决方案 - 更容易阅读。当我从 OLEDB 切换到本机时,嵌套选择(由 Maziar 建议)也可以工作。

        4. 我需要切换到“参数化查询”以避免 Conrad 指出的 sql 注入攻击。

        无论如何,当我切换到该方法时,上述建议有效。 而不是使用

        Provider=SQLOLEDB
        

        我用过:

        providerName="System.Data.SqlClient"
        

        我现在不引用 oledb(例如 oledbadapter),而是引用 sqlDataAdapter。我忽略了upper、ltrim 和trim 函数(因为事实证明它们不是问题)并专注于oledb 一直在扼杀的WITH。这是我要工作的内容:

            Dim conn As New SqlConnection("server=localhost;database=DB;Integrated Security=SSPI;")
            Dim sql As String
            Dim da As SqlDataAdapter
        
            Dim ds As DataSet = New DataSet()
            Dim tbl As DataTable = New DataTable
        
            conn = New SqlConnection()
            conn.ConnectionString =    ConfigurationManager.ConnectionStrings("DB").ConnectionString
        
            Sql = " WITH cte AS "
            sql = sql & "(lastname + firstname + middlename"
            Sql = Sql & "     + v) as userCompareStr FROM atable ) "
            sql = sql & "SELECT userCompareStr   FROM cte WHERE userCompareStr = '" & "GAPYLE1111" & "' ;"
        
            da = New SqlDataAdapter(sql, conn)
            da.Fill(ds)
            tbl = ds.Tables(0)
            TextBox2.Text = sql
        
            If tbl.Rows.Count < 1 Then
                TextBox1.Text = "no items"
            Else
                TextBox1.Text = tbl.Rows.Count & " items selected"
            End If
        
        
            conn.Dispose()
        

        另外,在 web.config 中,我添加了:

        我还没有添加 SQL 注入修复的东西,但我正在研究它,我现在确定这是我需要做的事情。我在这里找到了一些相关信息:

        http://msdn.microsoft.com/en-us/library/ff648339.aspx
        

        这里:

        http://weblogs.asp.net/cibrax/archive/2006/09/28/Parameterized-Queries-_2800_Oracle_2C00_-SQLServer_2C00_-OleDb_2900_.aspx
        

        但我需要一些时间来试验它。感谢您的帮助和指点。

        【讨论】:

          猜你喜欢
          • 2017-04-12
          • 1970-01-01
          • 2011-02-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-16
          • 1970-01-01
          相关资源
          最近更新 更多