2010-08-13 17 views
10

Estoy intentando crear una VISTA en SQL Server 2005.¿Cómo "declarar la variable escalar" en una vista en SQL Server (2005)

código SQL está funcionando como tal (Lo estoy usando en VS2008), pero en SQL Server no puedo guardarlo, ya que aparece el mensaje de error "Declare la variable escalar @StartDate" y "Declare la variable escalar @EndDate".

Aquí está el código:

WITH Calendar AS (SELECT  CAST(@StartDate AS datetime) AS Date 
    UNION ALL 
    SELECT  DATEADD(d, 1, Date) AS Expr1 
    FROM   Calendar AS Calendar_1 
    WHERE  (DATEADD(d, 1, Date) < @EndDate)) 
    SELECT  C.Date, C2.Country, COALESCE (SUM(R.[Amount of people per day needed]), 0) AS [Allocated testers] 
    FROM   Calendar AS C CROSS JOIN 
          dbo.Country AS C2 LEFT OUTER JOIN 
          dbo.Requests AS R ON C.Date BETWEEN R.[Start date] AND R.[End date] AND R.CountryID = C2.CountryID 
    GROUP BY C.Date, C2.Country 

Y mi pregunta es, por supuesto, - exactamente cómo debería declararlos?

traté de poner la siguiente por primera vez en el código:

DECLARE @StartDate smalldatetime 
DECLARE @EndDate smalldatetime 

Pero eso Dejase't hace el truco, justo lo que esperaba - que sólo me dio otro mensaje emergente:

"No se admite el constructo o declaración SQL de cursor de declaración".

Respuesta

12

Como ha mencionado Alex K, debe escribirlo como una función de tabla en línea valorada. Aquí está el article que describe al respecto.

En pocas palabras, la sintaxis sería algo así como

CREATE FUNCTION dbo.GetForPeriod 
    (@StartDate datetime, @EndDate datetime) 
RETURNS TABLE 
RETURN 
    SELECT [[ your column list ]] 
    FROM [[ table list] 
    WHERE [[some column] BETWEEN @StartDate AND @EndDate 

Usted puede tener una consulta de selección (por muy compleja, puede utilizar CTE). Y luego lo va a usar como

SELECT * FROM dbo.GetForPeriod('1-Jan-2010', '31-Jan-2010') 
+0

Bueno, voy a probarlo - Lo veo como una respuesta aceptable :-) –

+0

La desventaja de las funciones es que tienen un rendimiento muy pobre si quieres unirte o filtrarse en él. –

+1

@IanBoyd, lo que dices es generalmente cierto para las funciones escalar y de TVF de varias declaraciones. Sin embargo, la solución aquí utiliza la función de valores en la tabla en línea. AFAIK, SQL Server expandiría el UDF en la consulta (tal como se hace en la vista). lo que ha dicho, funcionaría mucho mejor en join/filter (suponiendo que las tablas participantes tengan los índices apropiados) o, al menos, no debería haber ninguna penalización (aparte del análisis adicional) para usar TVF en línea. Consulte la página http: //blogs.msdn.com/b/psssql/archive/2010/10/ 28/query-performance-and-multi-statement-table-valued-functions.aspx – VinayC

2

Si por VISTA quiere decir una vista nativo de SQL Server (CREATE VIEW ...) entonces no se puede utilizar variables locales en absoluto (que usaría una UDF con valores de tabla en su lugar).

Si quiere decir algo más, la adición de DECLARE @StartDate DATETIME, @EndDate DATETIME hace que la sentencia sea correcta, ¿es la totalidad del SQL?

+0

quiero decir que en los clics derecho de SQL Server Management Studio en el Carpeta "Vistas" y selecciona "Nueva vista ..."- He creado otras vistas de esta manera, y luego las uso en Visual Studio 2008 (C#) para usarlas al crear" TableAdapters ", por ejemplo. Bueno, ¿qué es un udf con valores de tabla? ¿Dónde y cómo lo hago? crearlo, ¿sabes? –

-1

intente reemplazar toda su @X, @Y con AX y AY, añadir a su código: FROM (SELECT X = 'literalX', Y = 'literalmente') A luego has puesto todos tus literales en un solo lugar y solo tienes una copia de ellos.

0

Aquí hay una consulta de muestra que utiliza CTE para emular muy bien la construcción de variables internas. Puede probarlo en su versión de SQL Server.

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 

salida obteniéndose:

status name 
12  dbo 
0  db_accessadmin 
0  db_securityadmin 
0  db_ddladmin 

también a través de 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 

también a través de 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 
Cuestiones relacionadas