Функции, определяемые в цикле продолжают получать доступ к той же переменной i
, в то время как ее значение изменяется. В конце цикла все функции указывают на ту же переменную, которая содержит последнее значение в цикле: эффект - то, что сообщило в примере.
, Чтобы оценить i
и использовать его значение, общий шаблон должен установить его как значение по умолчанию параметра: значения по умолчанию параметра оценены, когда def
оператор выполняется, и таким образом значение переменной цикла замораживается.
следующие работы как ожидалось:
flist = []
for i in xrange(3):
def func(x, i=i): # the *value* of i is copied in func() environment
return x * i
flist.append(func)
for f in flist:
print f(2)
ORDER BY
CASE WHEN @switch = 0 THEN Field1 END,
CASE WHEN @Switch = 1 THEN Field2 END
Один из способов - создать запрос примерно так:
CREATE PROCEDURE [dbo].[CLICK10_GetCP]
@switch AS BIT
AS
DECLARE
@SQL nvarchar(max)
SET @SQL N'SELECT
acct_nbr,
acct_name
FROM
acct
ORDER BY '
if(@switch)
BEGIN
@SQL = @SQL + ' acct_nbr '
END
ELSE
BEGIN
@SQL = @SQL + ' acct_Name '
END
Exec SP_ExecuteSQL @SQL
Грубый способ:
IF @switch = 1
BEGIN
SELECT
acct_nbr,
acct_name
FROM
acct
ORDER BY acct_nbr
END
ELSE
BEGIN
SELECT
acct_nbr,
acct_name
FROM
acct
ORDER BY acct_name
END
Вы также должны иметь возможность использовать CASE ... КОГДА я думаю:
SELECT
acct_nbr,
acct_name
FROM
acct
ORDER BY
CASE @switch
WHEN 1 THEN acct_nbr
WHEN 0 THEN acct_name
END
Я не совсем уверен Вы можете? В конечном итоге я бы сделал следующее:
CREATE PROCEDURE [dbo].[CLICK10_GetCP]
@switch AS BIT
AS
BEGIN
if @switch
begin
SELECT
acct_nbr,
acct_name
FROM
acct
ORDER BY
acct_nbr
end
else
begin
SELECT
acct_nbr,
acct_name
FROM
acct
ORDER BY
acct_name
end
END
GO
Я подумал, что вы можете изменить параметр на int и отсортировать по столбцу с этим порядковым номером:
CREATE PROCEDURE [dbo].[CLICK10_GetCP]
@ordinal AS INT
AS
BEGIN
SELECT
acct_nbr,
acct_name
FROM
acct
ORDER BY @Ordinal
END
GO
Это вызывает приятную ошибку (SQL2005):
Msg 1008, уровень 16 , Состояние 1, строка 4 Элемент SELECT, обозначенный ORDER BY номер 1 содержит переменную как часть выражения, определяющего положение столбца. Только переменные разрешено при заказе по выражению ссылка на имя столбца.
Поиск в Google нашел это решение здесь (SQL 2005 и выше):
CREATE PROCEDURE [dbo].[CLICK10_GetCP]
@switch AS BIT
AS
BEGIN
SELECT
acct_nbr,
acct_name
FROM
acct
ORDER BY CASE
WHEN @switch = 0 THEN (RANK() OVER (ORDER BY acct_nbr, acct_name))
WHEN @switch = 1 THEN (RANK() OVER (ORDER BY acct_name, acct_nbr))
END
GO
SELECT
acct_nbr,
acct_name
FROM
acct
ORDER BY case @switch when 1 then acct_name else acct_nbr end
Самый лаконичный подход:
CREATE PROCEDURE [dbo].[CLICK10_GetCP]
@switch AS BIT
AS
BEGIN
SELECT
acct_nbr,
acct_name
FROM
acct
ORDER BY
case @switch
when 1 then acct_nbr
when 0 then acct_name
end
END
GO
Это может привести к плохому плану выполнения для больших таблиц или может не работать вообще, если acc-nbr - это int, а acct-name - varchar.
Заключение двух отдельных запросов в операторы IF / ELSE может работать заметно лучше для больших наборов данных или быть единственным работоспособным подходом, если типы данных двух столбцов различаются.