如何解決 不能以 DISTINCT 方式選擇 text、ntext 或 image 數據類型


distinct去重,如果遇到text字段,可以用以下方法解決

 

1.用not exists

select * from tab a
where not exists (
  select 1 from tab b
  where b.col1 = a.col1
  and b.col2 = a.col2
  ...
  )

 

2.轉成字符型
CONVERT(VARCHAR(8000),你的字段)

select distinct * from (

select id, convert(varchar(8000), ntextCol) as colName from XXX

)

 

用EXISTS替換DISTINCT: 當提交一個包含一對多表信息(比如部門表和雇員表)的查詢時,避免在SELECT子句中使用DISTINCT. 一般可以考慮用EXIST替換, EXISTS 使查詢更為迅速,因為RDBMS核心模塊將在子查詢的條件一旦滿足后,立刻返回結果.

例子:

(低效):

SELECT  DISTINCT  DEPT_NO,DEPT_NAME  FROM  DEPT D , EMP E WHERE  D.DEPT_NO = E.DEPT_NO

(高效):

SELECT  DEPT_NO,DEPT_NAME  FROM  DEPT D  WHERE  EXISTS ( SELECT ‘X' FROM  EMP E  WHERE E.DEPT_NO = D.DEPT_NO);   

用EXISTS的確可以替代DISTINCT,不過以上方案僅適合DEPT_NO為唯一主鍵的情況。 如果要去掉重復記錄,需參照以下方法:

SELECT  * FROM  EMP WHERE  DEPT_NO EXISTS(select Max(DEPT_NO) FROM  DEPT D , EMP E  WHERE E.DEPT_NO = D.DEPT_NO GROUP BY D.DEPT_NO)  

 

得到重復記錄數

SELECT  * FROM  EMP WHERE  DEPT_NO NOT EXISTS(select Max(DEPT_NO) FROM  DEPT D , EMP E  WHERE E.DEPT_NO = D.DEPT_NO GROUP BY D.DEPT_NO)

 

 在我們進行sql注入的過程中常常會用到union查詢方法,大多數情況下使用union查詢法可以讓我們很快的知道目標的數據組織方式。然而當我們遇到ntext、text或image數據類型時,union查詢就不太管用了。以sql  server為例,在這種情況下會拋出如下錯誤:ntext 數據類型不能選為 DISTINCT,因為它不可比。

     這里,我以sql  server數據庫為測試環境來進行分析。因為ntext、text、image數據字段可能存儲非常多的數據,默認的情況下,數據庫為提高效率會強制排除以上類型的字段中的相同的數據,這樣就相當於在sql查詢語句中加入了distinct關鍵字。而又因為這種類型的數據量可能非常大,數據庫無法對這種類型的字段進行有效的比較,而distinct又要求數據庫進行數據比較,從而導致帶有unionr的sql語句執行錯誤,造成上述現象。

    了解了出錯的原理我們就可以在執等的sql語句中加入相應的條件來使sql能正確執行。從上面可以看出,sql語句無法執行的原因是因為數據庫去檢查union的數據是否相同,那么我們只需要去掉這個默認的條件就可以了。解決的方法就是在union關鍵字后邊加上“all”關鍵字。

    下面用實例來演示這種類型的union注入。首先創建兩個表: CREATE TABLE [dbo].[ntextTest](  [id]  [int] NOT NULL,  [name] [nchar](10) NULL,  [target] [ntext] NULL ) ON  [PRIMARY] TEXTIMAGE_ON [PRIMARY] CREATE TABLE [dbo].[support](  [col1]  [nchar](10) NULL,  [col2] [nchar](10) NULL ) ON  [PRIMARY] 然后分別在這兩個表中插入數據: insert into ntextTest  values(1,'aaa','adfsfs') insert into ntextTest  values(2,'test','aaaa') insert into support  values('aa','bb') 之后執行下列查詢: select * from ntextTest union  select 1,2,col1  from support 一如即往,沒有成功。再執行: select * from ntextTest union all select  1,col1,col2 from support 這次正常返回結果!接下來被卡住的sql注入可以繼續進行了。

      上面所講的問題的前提是ntext、text、image等數據類型出現在union查詢的前面部分,在進行sql注入時,注入對象原有的查詢語句中包含ntext數據類型即是這種情況。還有另一種情況是在我們注入時希望查詢ntext數據字段的內容。這種情況還有以有另一種操作方式。比如要注入一個地址:http://www.test.com/show.asp?id=1,假定其后后的sql查詢語句為:select id,productName,productInfo  from product where id=@id,其中productName和productInfo都為nvarchar類型,如果我們想要查詢這個網站后台的article表中的文章的內容(用content表示,為ntext類型)可以用substring  函數來實現。用substring 可以將ntext數據截取一部分出來作為nvarchar類型返回,這樣可以繞過ntext類型。如我們做如下構造:http://www.test.com/show.asp?id=1 and  1=2 union select 1,2,…,substring(content,1,200),...n from article where id=XX   下面附上substring詳細用法:

substring函數: {     返回值:返回字符、binary、text 或 image  表達式的一部分。     語法:SUBSTRING ( e­xpression , start , length  )      參數:         e­xpression:是字符串、二進制字符串、text、image、列或包含列的表達式。不要使用包含聚合函數的表達式。         start:是一個整數,指定子串的開始位置。            length:是一個整數,指定子串的長度(要返回的字符數或字節數)。      返回類型:            1)、如果  e­xpression 是支持的字符數據類型,則返回字符數據。            2)、如果  e­xpression 是支持的  binary 數據類型,則返回二進制數據。              返回字符串的類型與給定表達式的類型相同(表中顯示的除外)。

 

}

 

給定的表達式 返回類型
text varchar
image varbinary
ntext nvarchar

     注釋:             在字符數中必須指定使用 ntextchar varchar 數據類型的偏移量(start length)。在字節數中必須指定使用 textimagebinary varbinary 數據類型的偏             移量。

 

   

ps:之后以寫這篇文章是因為本人在注入過程中遇到了上面的問題,百度了好久都沒有找到有用的信息。相信很多像我一樣的小菜遇到這樣的問題也難以解決,希望這篇文章對小菜有所幫助。另本人初學安全技術,很多東西一知半解,難免出錯,如果老鳥們發現了還請指點!

 

 

用NOT EXISTS替代NOT IN 

  在子查詢中,NOT IN子句將執行一個內部的排序和合並。 無論在哪種情況下,NOT IN都是最低效的 (因為它對子查詢中的表執行了一個全表遍歷)。 為了避免使用NOT IN ,我們可以把它改寫成外連接(Outer Joins)或NOT EXISTS.

  例如:

 

  SELECT …   FROM EMP   WHERE DEPT_NO NOT IN (SELECT DEPT_NO   FROM DEPT   WHERE DEPT_CAT=’A’);

  為了提高效率。改寫為:

 (方法一: 高效)

 

  SELECT ….   FROM EMP A,DEPT B   WHERE A.DEPT_NO = B.DEPT(+)   AND B.DEPT_NO IS NULL   AND B.DEPT_CAT(+) = ‘A’

  (方法二: 最高效)

 

  SELECT ….   FROM EMP E   WHERE NOT EXISTS (SELECT ‘X’   FROM DEPT D   WHERE D.DEPT_NO = E.DEPT_NO   AND DEPT_CAT = ‘A’); 用EXISTS替換DISTINCT 

  當提交一個包含一對多表信息(比如部門表和雇員表)的查詢時,避免在SELECT子句中使用DISTINCT. 一般可以考慮用EXIST替換

  例如:

  低效:

 

  SELECT DISTINCT DEPT_NO,DEPT_NAME   FROM DEPT D,EMP E   WHERE D.DEPT_NO = E.DEPT_NO

 高效:

 

  SELECT DEPT_NO,DEPT_NAME   FROM DEPT D   WHERE EXISTS ( SELECT ‘X’   FROM EMP E   WHERE E.DEPT_NO = D.DEPT_NO);

  EXISTS 使查詢更為迅速,因為RDBMS核心模塊將在子查詢的條件一旦滿足后,立刻返回結果。

識別‘低效執行’的SQL語句

  用下列SQL工具找出低效SQL:

 

  SELECT EXECUTIONS , DISK_READS, BUFFER_GETS,   ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio,   ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run,   SQL_TEXT   FROM V$SQLAREA   WHERE EXECUTIONS>0   AND BUFFER_GETS > 0   AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8   ORDER BY 4 DESC;

  (雖然目前各種關於SQL優化的圖形化工具層出不窮,但是寫出自己的SQL工具來解決問題始終是一個最好的方法)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM