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

distinct去重,若是遇到text字段,能夠用如下方法解決html

 

1.用not existssql

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核心模塊將在子查詢的條件一旦知足後,馬上返回結果.優化

例子:網站

(低效):spa

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工具來解決問題始終是一個最好的方法)

相關文章
相關標籤/搜索