2009-11-06 37 views
76

¿Podemos pasar un parámetro a una vista en Microsoft SQL Server?¿Podemos pasar parámetros a una vista en SQL?

Me trataron de create view de la siguiente manera, pero no funciona:

create or replace view v_emp(eno number) as select * from emp where emp_id=&eno; 
+0

Una vista es un texto almacenado de SQL de una consulta de selección. Los parámetros están fuera de discusión. Cuando su consulta almacenada devuelve la columna con la que desea filtrar, puede hacerlo en la consulta de llamada. P.ej. "SELECT * FROM v_emp WHERE emp_id =?" – Epicurist

Respuesta

5

no. si debe utilizar una función definida por el usuario a la que puede pasar parámetros.

11

No, no puedes, como dijo Mladen Prajdic. Piense en una vista como un "filtro estático" en una tabla o una combinación de tablas. Por ejemplo: una vista puede combinar tablas Order y Customer para que obtenga una nueva "tabla" de filas de Order junto con nuevas columnas que contengan el nombre del cliente y el número de cliente (combinación de tablas). O bien, puede crear una vista que seleccione solo las órdenes no procesadas de la tabla Order (filtro estático).

Luego, debe seleccionar de la vista como seleccionaría de cualquier otra tabla "normal": todos los filtros "no estáticos" deben realizarse fuera de la vista (como "Obtener todos los pedidos para clientes llamados Miller" o "Obtenga pedidos sin procesar que llegaron el 24 de diciembre").

24

Hay 2 maneras de acheive lo que quiere por desgracia no se puede hacer usando una vista.

Puede crear una función definida por el usuario con valores de tabla que toma el parámetro que desee y devuelve un resultado de la consulta

O bien, puede hacer más o menos lo mismo, pero crear un procedimiento almacenado en lugar de una función definida por el usuario.

Por ejemplo

el procedimiento almacenado se vería

CREATE PROCEDURE s_emp 
(
    @enoNumber INT 
) 
AS 
SELECT 
    * 
FROM 
    emp 
WHERE 
    [email protected] 

o la función definida por el usuario se vería como

CREATE FUNCTION u_emp 
( 
    @enoNumber INT 
) 
RETURNS TABLE 
AS 
RETURN 
(
    SELECT  
     * 
    FROM  
     emp 
    WHERE  
     [email protected] 
) 
4

sin puede pasar el parámetro para el procedimiento a la vista

94

Como ya se ha indicado, no se puede.

Una posible solución sería implementar una función almacenada, como:

CREATE FUNCTION v_emp (@pintEno INT) 
RETURNS TABLE 
AS 
RETURN 
    SELECT * FROM emp WHERE [email protected]; 

Esto le permite utilizarla como una visión normal, con:

SELECT * FROM v_emp(10) 
+0

¿Cuáles son las diferencias prácticas entre esto y una vista? ¿Puedes asignar permisos de usuario para acceder solo a esta función? – MikeMurko

+0

En MySQL escribe un procedimiento almacenado y tiene la última declaración en el procedimiento, el conjunto de resultados que desea devolver. – bobobobo

+0

¿podemos usar esa solicitud sin ningún problema del código JDBC en Java? – mounaim

4

Una vista no es más que una declaración 'SELECCIONADA' predefinida. Entonces la única respuesta verdadera sería: No, no puedes.

Creo que lo que realmente quiere hacer es crear un procedimiento almacenado, donde en principio puede usar cualquier SQL válido para hacer lo que quiera, incluyendo aceptar parámetros y seleccionar datos.

Parece probable que realmente solo necesite agregar una cláusula Where cuando selecciona de su vista, pero en realidad no proporcionó suficientes detalles para estar seguro.

4

No, una vista es estática. Una cosa que puede hacer (dependiendo de la versión del servidor SQl) es indexar una vista.

En su ejemplo (consultar solo una tabla), una vista indizada no tiene ningún beneficio simplemente al consultar la tabla con un índice, pero si realiza muchas combinaciones en tablas con condiciones de unión, una vista indizada puede mejorar en gran medida el rendimiento.

4

podemos escribir un procedimiento almacenado con parámetros de entrada y luego usar ese procedimiento almacenado para obtener un conjunto de resultados de la vista. vea el ejemplo a continuación.

el procedimiento almacenado es

CREATE PROCEDURE [dbo].[sp_Report_LoginSuccess] -- [sp_Report_LoginSuccess] '01/01/2010','01/30/2010' 
@fromDate datetime, 
@toDate datetime, 
@RoleName varchar(50), 
@Success int 
as 
If @RoleName != 'All' 
Begin 
    If @Success!=2 
    Begin 
    --fetch based on true or false 
    Select * from vw_Report_LoginSuccess 
    where logindatetime between dbo.DateFloor(@fromDate) and dbo.DateSieling(@toDate) 
    And RTrim(Upper(RoleName)) = RTrim(Upper(@RoleName)) and [email protected] 
    End 
    Else 
    Begin 
    -- fetch all 
    Select * from vw_Report_LoginSuccess 
    where logindatetime between dbo.DateFloor(@fromDate) and dbo.DateSieling(@toDate) 
    And RTrim(Upper(RoleName)) = RTrim(Upper(@RoleName)) 
    End 

End 
Else 
Begin 
    If @Success!=2 
    Begin 
    Select * from vw_Report_LoginSuccess 
    where logindatetime between dbo.DateFloor(@fromDate) and dbo.DateSieling(@toDate) 
    and [email protected] 
End 
Else 
Begin 
    Select * from vw_Report_LoginSuccess 
    where logindatetime between dbo.DateFloor(@fromDate) and dbo.DateSieling(@toDate) 
End 

End 

y la vista desde el cual podemos obtener el conjunto de resultados se

CREATE VIEW [dbo].[vw_Report_LoginSuccess] 
AS 
SELECT  '3' AS UserDetailID, dbo.tblLoginStatusDetail.Success, CONVERT(varchar, dbo.tblLoginStatusDetail.LoginDateTime, 101) AS LoginDateTime, 
         CONVERT(varchar, dbo.tblLoginStatusDetail.LogoutDateTime, 101) AS LogoutDateTime, dbo.tblLoginStatusDetail.TokenID, 
         dbo.tblUserDetail.SubscriberID, dbo.aspnet_Roles.RoleId, dbo.aspnet_Roles.RoleName 
FROM   dbo.tblLoginStatusDetail INNER JOIN 
         dbo.tblUserDetail ON dbo.tblLoginStatusDetail.UserDetailID = dbo.tblUserDetail.UserDetailID INNER JOIN 
         dbo.aspnet_UsersInRoles ON dbo.tblUserDetail.UserID = dbo.aspnet_UsersInRoles.UserId INNER JOIN 
         dbo.aspnet_Roles ON dbo.aspnet_UsersInRoles.RoleId = dbo.aspnet_Roles.RoleId 
WHERE  (dbo.tblLoginStatusDetail.Success = 0) 
UNION all 
SELECT  dbo.tblLoginStatusDetail.UserDetailID, dbo.tblLoginStatusDetail.Success, CONVERT(varchar, dbo.tblLoginStatusDetail.LoginDateTime, 101) 
         AS LoginDateTime, CONVERT(varchar, dbo.tblLoginStatusDetail.LogoutDateTime, 101) AS LogoutDateTime, dbo.tblLoginStatusDetail.TokenID, 
         dbo.tblUserDetail.SubscriberID, dbo.aspnet_Roles.RoleId, dbo.aspnet_Roles.RoleName 
FROM   dbo.tblLoginStatusDetail INNER JOIN 
         dbo.tblUserDetail ON dbo.tblLoginStatusDetail.UserDetailID = dbo.tblUserDetail.UserDetailID INNER JOIN 
         dbo.aspnet_UsersInRoles ON dbo.tblUserDetail.UserID = dbo.aspnet_UsersInRoles.UserId INNER JOIN 
         dbo.aspnet_Roles ON dbo.aspnet_UsersInRoles.RoleId = dbo.aspnet_Roles.RoleId 
WHERE  (dbo.tblLoginStatusDetail.Success = 1) AND (dbo.tblUserDetail.SubscriberID LIKE N'P%') 
5

Una manera hacky hacerlo sin procedimientos almacenados o funciones sería la creación de una tabla de configuraciones en su base de datos, con las columnas Id, Param1, Param2, etc. Inserte una fila en esa tabla que contenga los valores Id = 1, Param1 = 0, Param2 = 0, etc. Luego, puede agregar una combinación a esa tabla en su ver para crear el efecto deseado y actualizar la tabla de configuraciones antes de ejecutar el juego w. Si tiene varios usuarios actualizando la tabla de configuraciones y ejecutando la vista al mismo tiempo, las cosas podrían salir mal, pero de lo contrario debería funcionar correctamente. Algo así como:

CREATE VIEW v_emp 
AS 
SELECT  * 
FROM  emp E 
INNER JOIN settings S 
ON   S.Id = 1 AND E.emp_id = S.Param1 
+7

Sí, tienes razón. Esta es una solución horrible. – Ben

+0

sería terrible usarlo para una solicitud de visualización. Pero es realmente utilizable, como configuración/escenario/entorno, utilizar dichos parámetros ocultos. Un Plus para mí por eso. – TPAKTOPA

3

Como sé, la vista puede ser algo así como seleccionar el comando. También puede añadir parámetros a este selecto por ejemplo, en donde las declaraciones como esta:

WHERE (exam_id = @var) 
+0

Esto debería ser aceptado como respuesta. Simple, fácil y directo. Muchas gracias :) – FrenkyB

5

¿Por qué se necesita un parámetro a la vista? Puede usar la cláusula WHERE.

create view v_emp as select * from emp ; 

y la consulta debe hacer el trabajo:

select * from v_emp where emp_id=&eno; 
+3

En algunos casos habrá una gran mejora en el rendimiento, cuando se trata de un 'DÓNDE' para la tabla, en lugar de un' DONDE' para la vista. –

3

Si no desea utilizar una función, puede usar algo como esto

-- VIEW 
CREATE VIEW [dbo].[vwPharmacyProducts] 
AS 
SELECT  PharmacyId, ProductId 
FROM   dbo.Stock 
WHERE  (TotalQty > 0) 

-- Use of view inside a stored procedure 
CREATE PROCEDURE [dbo].[usp_GetProductByFilter] 
( @pPharmacyId int) AS 

IF @pPharmacyId = 0 BEGIN SET @pPharmacyId = NULL END 

SELECT P.[ProductId], P.[strDisplayAs] FROM [Product] P 
WHERE (P.[bDeleted] = 0) 
    AND (P.[ProductId] IN (Select vPP.ProductId From vwPharmacyProducts vPP 
          Where vPP.PharmacyId = @pPharmacyId) 
         OR @pPharmacyId IS NULL 
     ) 

esperanza de que ayudará

1

Puede eludir solo para ejecutar la vista, SQL llorará y llorará, pero solo haga esto y ejecútelo. No puedes guardar

create or replace view v_emp(eno number) as select * from emp where (emp_id = @Parameter1); 
2

Aquí es una opción que no he visto hasta ahora:

Simplemente añadir la columna que desea restringir a la vista:

create view emp_v as (
select emp_name, emp_id from emp; 
) 

select emp_v.emp_name from emp_v 
where emp_v.emp_id = (id to restrict by) 
1

Tu punto de vista puede hacer referencia a alguna tabla externa que contiene tus parámetros

Como mencionan otros, la vista en SQL Server no puede tener parámetros de entrada externos.Sin embargo, puede falsificar fácilmente una variable en su vista utilizando CTE. 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