我目前正在維護大量的SQL查詢。其中一些是通過複製/粘貼操作創建的,然後刪除不必要的字段,有時忘記刪除這些字段來自哪裏的表。在SQL查詢中查找未使用的連接
我正在尋找一個工具(或除了眼睛和大腦以外的任何東西),給定一個SQL查詢,將分析哪些連接表在SELECT部分中沒有選擇字段。
你知道這樣的工具嗎?
謝謝
我目前正在維護大量的SQL查詢。其中一些是通過複製/粘貼操作創建的,然後刪除不必要的字段,有時忘記刪除這些字段來自哪裏的表。在SQL查詢中查找未使用的連接
我正在尋找一個工具(或除了眼睛和大腦以外的任何東西),給定一個SQL查詢,將分析哪些連接表在SELECT部分中沒有選擇字段。
你知道這樣的工具嗎?
謝謝
打趣的工具可能存在,但它只能保證,如果說所有地方滿足以下條件加盟是正確的
Probabl y爲什麼在SQL解析器中沒有確定性的警告,我們可以說C#中一個未使用的變量。但是創建一個SQL檢查器可能是值得的,它會查找其中一些條件,並讓用戶知道這裏有可能進行優化。
只是因爲沒有字段在SELECT中引用,這並不意味着該連接是不查詢和結果的邏輯很重要,如果被刪除的加入可能會改變。
考慮一個簡單的例子:返回誰在2011年
SELECT DISTINCT c.CustomerName
FROM Customer c
INNER JOIN Sales s
ON c.CustomerID = s.CustomerID
AND s.SalesDate >= '2011-01-01'
從銷售表中沒有列在SELECT返回購買的物品所有客戶的名稱,但該連接是在返回正確的關鍵結果集。
底線:我認爲你需要一個人眼/大腦代碼檢查來正確地清理事情。
+1,這是一個非常重要的考慮 – Lamak 2011-04-06 14:37:07
我很清楚這一點,我問這個問題,因爲我知道在我的情況下,聯接只是檢索額外的數據。不管怎麼說,還是要謝謝你。順便說一句,我會很感激,如果你會提供一個答案的原始問題:) – 2011-04-06 20:30:51
@Johann布萊斯:我相信我回答你的原始問題與我的答案的最後一句話,但我會在這裏再次修改它:沒有工具,您需要進行手動代碼審查。 – 2011-04-06 20:34:37
下面的函數用count(*)替換所有選擇的字段,第二部分刪除不必要的連接。此函數僅適用於具有別名的表,並且應該針對非常複雜的查詢進行測試,並且如果在聯接條件中存在內部查詢,則該函數將無法工作。
function sql_query_count($sql) {
//replace select fields with count(*)
$a = true;
$b = 0;
$first_select = stripos($sql, 'select ');
$last_from = 0;
$i = 0;
while($a){
$i++;
$b = stripos($sql, ' from ',$last_from);
$c = strripos(substr($sql, $last_from, $b), 'select ');
if ($c == $first_select || $c === false || $i>100) $a = false;
$last_from = $b+6;
}
if (stripos($sql, 'order by') !== false)
$sql = substr($sql, 0, stripos($sql, 'order by'));
$sql1 = 'select count(*) as c ' . substr($sql, $b);
//remove unnecessary joins
$joins = preg_split("/ join /i", $sql1);
$join_count = count($joins);
$join_type = '';
if (count($joins)>1){
for ($index = 0; $index < $join_count+2; $index++) {
$sql_new = '';
$where = '';
$i = 0;
foreach ($joins as $key => $value) { $i++;
$parts = preg_split("/ where /i", trim($value));
$value = $parts[0];
unset($parts[0]);
$where = implode(' where ', $parts);
$occurence_count = 0;
if ($i > 1) {
$a = explode(' on ', $value);
$c = preg_replace('!\s+!', ' ', trim($a[0]));
$c = explode(' ', $c);
$occurence_count = substr_count($sql1, ' '.$c[1].'.')+substr_count($sql1, '='.$c[1].'.');
}
$t = explode(' ', $value);
$j = '';
if (trim(strtolower($t[count($t) - 1])) == 'inner'){
$j = 'inner';
unset($t[count($t) - 1]);
} else if (trim(strtolower($t[count($t) - 2])).' '.trim(strtolower($t[count($t) - 1])) == 'left outer'){
$j = 'left outer';
unset($t[count($t) - 1]);
unset($t[count($t) - 1]);
}
if ($occurence_count == 0 || $occurence_count > 1) $sql_new.= ' '.$join_type.(($join_type!='')?' join ':'').implode(' ', $t);
$join_type = $j;
}
$sql_new .= ' where '.$where;
$sql1 = $sql_new;
$joins = preg_split("/ join /i", $sql1);
}
}
return $sql1;
}
如上所述,識別冗餘內連接將是一個問題,因爲有時它們對返回的數據產生影響,即使沒有數據實際上是從這些表中選擇。
說的是,識別冗餘的左連接是可能的。我正在使用automatic query optimizer來自動優化SQL查詢。除其他外,它可以識別多餘的左連接。
您還需要確保它不在SUB-SELECT或相關子查詢中引用...... – JNK 2011-04-06 14:58:09
謝謝,我接受您的答案,因爲您提供了更多標準來構建此類工具。 – 2011-04-07 04:52:20