SQL Views - немає змінних?


83

Чи можна оголосити змінну в поданні? Наприклад:

Declare @SomeVar varchar(8) = 'something'

видає мені синтаксичну помилку:

Неправильний синтаксис біля ключового слова "Оголосити".

Відповіді:


66

Ви праві. Місцеві змінні заборонені в ПЕРЕГЛЯДІ.

Ви можете встановити локальну змінну в табличній функції, яка повертає набір результатів (як це робить подання).

http://msdn.microsoft.com/en-us/library/ms191165.aspx

напр

CREATE FUNCTION dbo.udf_foo()
RETURNS @ret TABLE (col INT)
AS
BEGIN
  DECLARE @myvar INT;
  SELECT @myvar = 1;
  INSERT INTO @ret SELECT @myvar;
  RETURN;
END;
GO
SELECT * FROM dbo.udf_foo();
GO

Чи схожа його ефективність на вигляд?
RaRdEvA

Ні, TVF часто бувають повільнішими. "Функції табличного значення (TVF) SQL Server здаються гарною ідеєю, але вони маскують безліч потенційних проблем із продуктивністю. TVF змушують частини плану виконання залишатися послідовними (вони уникатимуть паралельності), вони дають неправильні оцінки рядків, і багатоканальний TVF може навіть не отримати найкращу доступну оптимізацію. Коротше кажучи - TVFs смердять ". brentozar.com/blitzcache/tvf-join
wp78de

49

Ви можете використовувати WITH для визначення своїх виразів. Потім виконайте простий Sub-SELECT, щоб отримати доступ до цих визначень.

CREATE VIEW MyView
AS
  WITH MyVars (SomeVar, Var2)
  AS (
    SELECT
      'something' AS 'SomeVar',
      123 AS 'Var2'
  )

  SELECT *
  FROM MyTable
  WHERE x = (SELECT SomeVar FROM MyVars)

3
це константи, а не змінні!
Владислав

2
@Vladislav Він може так само легко використовувати (відфільтровані?) Дані з таблиці.
Додекафон

18

РЕДАГУВАТИ: Я спробував використати CTE для моєї попередньої відповіді, яка була неправильною, як зазначив @bummi. Натомість цей параметр повинен працювати:

Ось один із варіантів використання КРОСОВОГО ЗАСТОСУВАННЯ для вирішення цієї проблеми:

SELECT st.Value, Constants.CONSTANT_ONE, Constants.CONSTANT_TWO
FROM SomeTable st
CROSS APPLY (
    SELECT 'Value1' AS CONSTANT_ONE,
           'Value2' AS CONSTANT_TWO
) Constants

Дякуємо за виправлення - оновлено, щоб замість нього використовувати КРОСОВЕ ЗАСТОСУВАННЯ.
Даніель Ніл

Це працює, але чи не повторно ініціалізуються стовпці Cross Application для кожного рядка? Особливо для розрахункових значень, які означали б великі втрати продуктивності. Дуже сумно, що Local Variable та CTE недоступні у поданні, хтось знає, чому?
T_D

1
@T_D ви можете створити та використовувати "CTE" у "View".
Чарівний

6

@datenstation мала правильну концепцію. Ось робочий приклад, який використовує CTE для кешування імен змінних:

CREATE VIEW vwImportant_Users AS
WITH params AS (
    SELECT 
    varType='%Admin%', 
    varMinStatus=1)
SELECT status, name 
    FROM sys.sysusers, params
    WHERE status > varMinStatus OR name LIKE varType

SELECT * FROM vwImportant_Users

також через JOIN

WITH params AS ( SELECT varType='%Admin%', varMinStatus=1)
SELECT status, name 
    FROM sys.sysusers INNER JOIN params ON 1=1
    WHERE status > varMinStatus OR name LIKE varType

також через CROSS APPLY

WITH params AS ( SELECT varType='%Admin%', varMinStatus=1)
SELECT status, name 
    FROM sys.sysusers CROSS APPLY params
    WHERE status > varMinStatus OR name LIKE varType

4

Використання функцій, як згадано spencer7593, є правильним підходом для динамічних даних. Що стосується статичних даних, то більш ефективний підхід, який узгоджується з дизайном даних SQL (на відміну від шаблону написання масивного процедурного коду в sprocs), полягає у створенні окремої таблиці зі статичними значеннями та приєднанні до неї. Це надзвичайно вигідно з точки зору продуктивності, оскільки SQL Engine може будувати ефективні плани виконання навколо JOIN, і ви також можете додавати індекси, якщо це необхідно.

Недоліком використання функцій (або будь-яких вбудованих обчислюваних значень) є те, що виноска трапляється для кожного поверненого потенційного рядка, що є дорогим. Чому? Оскільки SQL повинен спочатку створити повний набір даних з обчисленими значеннями, а потім застосувати до цього набору речення WHERE.

Дев'ять разів із десяти у ваших запитах не потрібно мати динамічно обчислюваних значень комірок. Набагато краще зрозуміти, що вам знадобиться, потім розробити модель даних, яка її підтримує, і заповнити цю модель даними напівдинамічними даними (наприклад, за допомогою пакетних завдань) і використовувати SQL Engine для важких робіт за допомогою стандартного SQL .


3

Так, це правильно, ви не можете мати змінних у поданнях (є й інші обмеження).

Представлення можна використовувати для випадків, коли результат можна замінити оператором select.


Функцію таблиці можна замінити в операторі select, і вона має локальні змінні.
JeffO

Ви кажете, оскільки оператор select не може мати локальних змінних, а подання також не може?
JeffO

1
@JeffO "ти не можеш мати змінних у поданнях" - це те, що я сказав. Це незрозуміло?
Хоган

Це останнє речення. Подання може замінити оператор select, але яке відношення це має до змінних? Чи не може таблична функція замінити оператор select, але включити змінні?
JeffO

1
Функцію таблиці можна також замінити оператором select, але функції таблиці не можна використовувати скрізь, що може подання, наприклад об'єднання. Він намагається сказати, що подання може замінити одне твердження select, але не може замінити декілька тверджень. Ключове слово BEGIN недійсне в операторі CREATE VIEW, а також вбудованій функції. Це було б потрібно для створення сценарію багатостаціонарності. Процедури або кілька функцій оператора, мабуть, найкращий спосіб зробити це.
Арлен Бейлер,

1

Що я роблю, це створити представлення, яке виконує те саме виділення, що і змінна таблиці, і зв’язати цей вид з другим поданням. Таким чином, подання можна вибрати з іншого подання. Цим самим досягається той самий результат


2
Бен, це, швидше за все, може спричинити проблеми з продуктивністю, якщо ти не маєш справу з дуже маленькими таблицями.
логіколог

Навіть із дуже маленькою таблицею (3 записи), подання з мільйонами записів викликає великі проблеми з продуктивністю.
st_stefanov

0

Як часто потрібно оновлювати вид? У мене є подібний випадок, коли нові дані надходять раз на місяць; тоді я повинен завантажувати його, а під час процесів завантаження я повинен створювати нові таблиці. На той момент я змінюю свій погляд, щоб врахувати зміни. Я використовував як основу інформацію в цьому іншому питанні:

Динамічно створюйте подання та синоніми

Там пропонується робити це двома способами:

  1. з використанням синонімів.
  2. Використання динамічного SQL для створення подання (саме це допомогло мені досягти результату).
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.