Как мне получить SQL SELECT @variable = назначения выражений, чтобы работать как электронная таблица? - PullRequest
1 голос
/ 08 мая 2009

Отказ от ответственности: это «вопрос с ответом и ответом», опубликованный в соответствии с утверждением часто задаваемых вопросов о том, что «совершенно нормально задавать и отвечать на свой собственный вопрос программирования». Его цель - побудить членов сообщества разработчиков SQL Anywhere использовать StackOverflow, заполнив тег «sqlanywhere» реальным контентом. Любые изменения, как и другие ответы, помечены как «wiki сообщества», чтобы облегчить это, а также избежать претензий к игровой системе репутации.

Я пишу хранимую процедуру для SQL Anywhere 9.0.2, вот код:

...
declare
@v_d datetime, @v_d1 datetime, @v_d2 datetime
....
select @v_d1 = @v_d, @v_d2 = dateadd(dd, 1, @v_d1)
...

оказывается, что @ v_d2 не будет установлен должным образом. если я изменю его на:

...
declare
@v_d datetime, @v_d1 datetime, @v_d2 datetime
....
select @v_d1 = @v_d
select @v_d2 = dateadd(dd, 1, @v_d1)
...

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

...
declare
@v_d datetime, @v_d1 datetime, @v_d2 datetime
....
begin
   select @v_d1 = @v_d
end
begin
   select @v_d2 = dateadd(dd, 1, @v_d1)
end
...

теперь все работает нормально, выглядит глупо. мой вопрос: это известная проблема? или, может быть, я мог бы сделать это более аккуратно? любой комментарии будут оценены. Спасибо!

1 Ответ

4 голосов
/ 08 мая 2009

Вы ищете автоматический пересчет в стиле электронных таблиц для назначения переменных хоста в списке SELECT Transact-SQL. Мне любопытно, делают ли это Microsoft SQL Server или Sybase ASE, но это SQL Anywhere ...

Из поведения вашего исходного кода это выглядит как ссылки на переменные хоста (ссылка на @ v_d1 в обращении к dateadd) всегда ссылаются на значения, которые существовали на момент запуска оператора (ноль), а не на пересчитанное значение ( значение из @v_d):

CREATE PROCEDURE p AS
declare
@v_d datetime, @v_d1 datetime, @v_d2 datetime
SELECT @v_d = CURRENT TIMESTAMP
select @v_d1 = @v_d, @v_d2 = dateadd(day, 1, @v_d1)
SELECT @v_d, @v_d1, @v_d2
GO

SELECT * FROM p();

@v_d,@v_d1,@v_d2
'2009-05-08 15:13:43.964','2009-05-08 15:13:43.964',(NULL)

Вы сообщаете, что ваша вторая версия (отдельные операторы SELECT) не работает, но у меня работает следующее:

DROP PROCEDURE p;

CREATE PROCEDURE p AS
declare
@v_d datetime, @v_d1 datetime, @v_d2 datetime
SELECT @v_d = CURRENT TIMESTAMP
select @v_d1 = @v_d
select @v_d2 = dateadd(dd, 1, @v_d1)
SELECT @v_d, @v_d1, @v_d2
GO

SELECT * FROM p();

@v_d,@v_d1,@v_d2
'2009-05-08 15:12:54.339','2009-05-08 15:12:54.339','2009-05-09 15:12:54.339'

Перерасчет в стиле электронной таблицы, который вы ищете, применяется для выбора элементов списка, закодированных как «выражение AS-идентификатор» (но это не совсем то, что вам нужно) ...

DROP PROCEDURE p;

CREATE PROCEDURE p AS
declare @v_d datetime
SELECT CURRENT TIMESTAMP INTO @v_d
select @v_d AS v_d, dateadd(day, 1, v_d) AS v_d1, dateadd(day, 1, v_d1) AS v_d2
GO

SELECT * FROM p();

v_d,v_d1,v_d2
'2009-05-08 15:14:27.292','2009-05-09 15:14:27.292','2009-05-10 15:14:27.292'

Если вы хотите выполнить перерасчет в стиле электронных таблиц И хотите, чтобы вам присваивались переменные хоста, я предлагаю вам переключиться на диалект Watcom-SQL, чтобы вы могли использовать список INTO:

DROP PROCEDURE p;

CREATE PROCEDURE p() BEGIN
   DECLARE @v_d  datetime;
   DECLARE @v_d1 datetime;
   DECLARE @v_d2 datetime;
SET @v_d = CURRENT TIMESTAMP;
SELECT @v_d AS v_d, 
       dateadd(day, 1, v_d) AS v_d1, 
       dateadd(day, 1, v_d1) AS v_d2
  INTO @v_d,
       @v_d1,
       @v_d2;
SELECT @v_d,
       @v_d1,
       @v_d2;
END;

SELECT * FROM p();

@v_d,@v_d1,@v_d2
'2009-05-08 15:27:09.808','2009-05-09 15:27:09.808','2009-05-10 15:27:09.808'

Поведение аналогично в версиях SQL Anywhere 9.0.2 и 11.0.1.

Брек

...