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 ( expression , start , length ) 參數: expression:是字符串、二進制字符串、text、image、列或包含列的表達式。不要使用包含聚合函數的表達式。 start:是一個整數,指定子串的開始位置。 length:是一個整數,指定子串的長度(要返回的字符數或字節數)。 返回類型: 1)、若是 expression 是支持的字符數據類型,則返回字符數據。 2)、若是 expression 是支持的 binary 數據類型,則返回二進制數據。 返回字符串的類型與給定表達式的類型相同(表中顯示的除外)。
}
給定的表達式 | 返回類型 |
---|---|
text | varchar |
image | varbinary |
ntext | nvarchar |
註釋: 在字符數中必須指定使用 ntext、char 或 varchar 數據類型的偏移量(start 和 length)。在字節數中必須指定使用 text、image、binary 或 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工具來解決問題始終是一個最好的方法)