2012-02-28 3 views
3

В C#, если я запускаю следующее.Соединяет ли SQL только минимальное количество условий?

if(obj.a() && obj.b()){ 
    // do something 
} 

Функция b будет выполнять только если a возвратит истину. То же самое происходит ниже?

select 
    * 
from 
    tablea a 
    inner join tableb b 
     isnumeric(b.col1) = 1 
     and cast(b.col1 as int) = a.id 

Будет ли cast выполняться только тогда, когда b.col1 является числовым?

+1

родственный: [Является ли SQL WHERE оценивается положение короткого замыкания] (http://stackoverflow.com/questions/789231/is-the -sql-where-clause-short-circuit-rated) – AakashM

ответ

2

Вы можете моделировать оценку короткого замыкания с использованием выражения CASE.

ON CASE WHEN ISNUMERIC(b.col1) = 1 
     THEN CAST(b.col1 AS int) 
     ELSE NULL 
    END = a.id 
+1

+1 Это единственный безопасный способ сделать это. Однако 'ELSE NULL' является избыточным. –

1

От HERE:

No. Если приоритет не определяется форматов или с помощью скобок, эффективная оценка выражений, как правило, выполняются слева направо. Тем не менее, зависит от реализации, независимо от того, действительно ли выражения оцениваются слева направо, особенно когда операнды или операторы могут вызывать условия для повышения или если результаты выражений могут быть определены без полной оценки всех частей выражения.

2

Это касается короткого circuat оценки в SQL-сервере глубоко:

http://www.sqlservercentral.com/articles/T-SQL/71950/

Короче говоря: порядок оценки зависит от оптимизатора запросов.

Редактировать: Как отметил Мартин, это не гарантирует заказ, поскольку он также может быть оптимизирован. Из приведенной выше ссылки (я должен был прочитать его полностью):

При запуске против SQL Server 2000, не генерируется никакой ошибки, но SQL Server 2005 и 2008 лет осуществить оптимизацию, чтобы подтолкнуть не-SARGable предикатов в сканирование индекса из подзапроса, которое приводит к ошибке оператора .

Чтобы избежать этой проблемы, запрос можно переписать с использованием выражения CASE , возможно, немного неясного, но гарантированного не сработает.

Таким образом, это должно гарантировать, что ISNUMERIC будет оцениваться первым:

SELECT aData.*,bData.* 
FROM #TableA aData INNER JOIN #TableB bData 
ON aData.id = CASE ISNUMERIC(bData.col1) WHEN 1 THEN CAST(bData.col1 AS INT) END 

Игнорируйте мой первый подход (который не может работать каждый раз):

Вы должны изменить ваш присоединиться к убедитесь, что данные оцениваются правильно :

SELECT aData.*,bData.* 
FROM #TableA aData INNER JOIN 
(
    SELECT col1 
    FROM #TableB b 
    WHERE ISNUMERIC(b.col1) = 1 
) AS bData 
ON aData.id = CAST(bData.Col1 AS int) 

Образец данных:

create table #TableA(id int) 
create table #TableB(col1 varchar(10)) 

insert into #TableA values(1); 
insert into #TableA values(2); 
insert into #TableA values(3); 
insert into #TableA values(4); 

insert into #TableB values('1'); 
insert into #TableB values('2'); 
insert into #TableB values(null); 
insert into #TableB values('4abc'); 

SELECT aData.*,bData.* 
FROM #TableA aData INNER JOIN 
(
    SELECT col1 
    FROM #TableB b 
    WHERE ISNUMERIC(b.col1) = 1 
) AS bData 
ON aData.id = CAST(bData.Col1 AS int) 

drop table #TableA; 
drop table #TableB; 

Результат:

id col1 
1 1 
2 2 
+1

@Martin: Спасибо, отредактировал мой ответ. –

Смежные вопросы