web-dev-qa-db-fra.com

Peut-on passer des paramètres à une vue en SQL?

Pouvons-nous passer un paramètre à une vue dans Microsoft SQL Server?

J'ai essayé de create view de la manière suivante, mais cela ne fonctionne pas: 

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

Comme déjà dit, vous ne pouvez pas. 

Une solution possible serait d'implémenter une fonction stockée, telle que: 

CREATE FUNCTION v_emp (@pintEno INT)
RETURNS TABLE
AS
RETURN
   SELECT * FROM emp WHERE emp_id=@pintEno;

Cela vous permet de l'utiliser comme une vue normale, avec:

SELECT * FROM v_emp(10)
107
Alex Bagnolini

Il y a 2 façons de réaliser ce que vous voulez, malheureusement, aucune ne peut être effectuée à l'aide d'une vue.

Vous pouvez soit créer une fonction définie par l'utilisateur, à valeur de table, qui prend le paramètre souhaité et renvoie un résultat de requête.

Ou vous pouvez faire à peu près la même chose mais créer une procédure stockée à la place d'une fonction définie par l'utilisateur.

Par exemple

la procédure stockée ressemblerait

CREATE PROCEDURE s_emp
(
    @enoNumber INT
) 
AS 
SELECT
    * 
FROM
    emp 
WHERE 
    emp_id=@enoNumber

Ou la fonction définie par l'utilisateur ressemblerait à

CREATE FUNCTION u_emp
(   
    @enoNumber INT
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT    
        * 
    FROM    
        emp 
    WHERE     
        emp_id=@enoNumber
)
29
Gavin

Non, vous ne pouvez pas, comme l'a dit Mladen Prajdic. Imaginez une vue comme un "filtre statique" sur une table ou une combinaison de tables. Par exemple: une vue peut combiner les tables Order et Customer afin d'obtenir une nouvelle "table" de lignes de Order ainsi que de nouvelles colonnes contenant le nom du client et son numéro (combinaison de tables). Vous pouvez également créer une vue qui sélectionne uniquement les ordres non traités dans la table Order (filtre statique).

Vous sélectionneriez ensuite dans la vue comme vous le feriez dans n'importe quelle autre table "normale" - tout filtrage "non statique" doit être effectué en dehors de la vue (comme "Obtenir toutes les commandes pour les clients appelés Miller" ou "Obtenir les commandes non traitées qui est entré le 24 décembre ").

13
Thorsten Dittmar

Une façon simple de le faire sans procédures ni fonctions stockées serait de créer une table de paramètres dans votre base de données, avec les colonnes Id, Param1, Param2, etc. Insérez une ligne dans cette table contenant les valeurs Id = 1, Param1 = 0, Param2 = 0, etc. Vous pouvez ensuite ajouter une jointure à cette table dans votre vue pour créer l'effet souhaité et mettre à jour la table de paramètres avant d'exécuter la vue. Si plusieurs utilisateurs mettent à jour le tableau de paramètres et exécutent la vue simultanément, des problèmes peuvent se produire, mais cela devrait fonctionner correctement. Quelque chose comme:

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

Normalement, les vues ne sont pas paramétrées. Mais vous pouvez toujours injecter des paramètres. Par exemple, en utilisant contexte de session :

CREATE VIEW my_view
AS
SELECT *
FROM tab
WHERE num = SESSION_CONTEXT(N'my_num');

Invocation:

EXEC sp_set_session_context 'my_num', 1; 
SELECT * FROM my_view;

Et un autre:

EXEC sp_set_session_context 'my_num', 2; 
SELECT * FROM my_view;

DBFiddle Demo

Il en va de même pour Oracle (bien entendu, la syntaxe de la fonction de contexte est différente).

8
Lukasz Szozda

Pourquoi avez-vous besoin d'un paramètre en vue? Vous pouvez simplement utiliser la clause WHERE.

create view v_emp as select * from emp ;

et votre requête devrait faire le travail:

select * from v_emp where emp_id=&eno;
7
Mahesh

no . si vous devez ensuite utiliser une fonction définie par l'utilisateur à laquelle vous pouvez passer des paramètres.

6
Mladen Prajdic

nous pouvons écrire une procédure stockée avec des paramètres d'entrée, puis utiliser cette procédure stockée pour obtenir un ensemble de résultats à partir de la vue ... voir l'exemple ci-dessous.

la procédure stockée est

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 Success=@Success
   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 Success=@Success
 End
 Else
 Begin
  Select * from vw_Report_LoginSuccess
  where logindatetime between  dbo.DateFloor(@fromDate) and dbo.DateSieling(@toDate)
 End

End

et la vue à partir de laquelle nous pouvons obtenir le jeu de résultats est

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
sunil

Comme je le sais, la vue peut ressembler à la commande select . Vous pouvez également ajouter des paramètres à cette sélection, par exemple dans les instructions where telles que

 WHERE  (exam_id = @var)
5
Reza Ameri

Une vue n'est rien d'autre qu'une instruction 'SELECT' prédéfinie. Donc, la seule vraie réponse serait: non, vous ne pouvez pas.

Je pense que ce que vous voulez vraiment faire est de créer une procédure stockée, dans laquelle vous pouvez en principe utiliser tout code SQL valide pour faire ce que vous voulez, y compris accepter des paramètres et sélectionner des données.

Il semble probable que vous n’ayez vraiment besoin que d’ajouter une clause where lorsque vous sélectionnez votre vue, mais vous n’avez pas fourni suffisamment de détails pour en être sûr.

5
Kris

Non, une vue est statique. Une chose que vous pouvez faire (en fonction de la version du serveur SQL) est d’indexer une vue.

Dans votre exemple (interrogation d'une seule table), une vue indexée n'a aucun intérêt à interroger simplement la table avec un index. Toutefois, si vous effectuez de nombreuses jointures sur des tables avec des conditions de jointure, une vue indexée peut considérablement améliorer les performances.

4
John

Non, une vue n'est pas interrogée différemment de SÉLECTION dans une table.

Pour faire ce que vous voulez, utilisez une fonction définie par l'utilisateur table-value avec un ou plusieurs paramètres

4
MartW

Si vous ne voulez pas utiliser une fonction, vous pouvez utiliser quelque chose comme ceci

-- 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
        )

J'espère que ça va aider

3
Adnan Badar

no vous pouvez passer le paramètre à la procédure en vue

3
aicuxiao

Voici une option que je n'ai pas vue jusqu'à présent:

Ajoutez simplement la colonne que vous souhaitez restreindre à la vue:

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)
2
FarajDaoud

Vous pouvez ignorer simplement pour exécuter la vue, SQL va vinifier et pleurer mais faites-le et exécutez-le! Vous ne pouvez pas enregistrer.

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

Votre vue peut référencer une table externe contenant vos paramètres. 

Comme d'autres l'ont mentionné, la vue dans SQL Server ne peut pas avoir de paramètres d'entrée externes. Cependant, vous pouvez facilement simuler une variable dans votre vue en utilisant CTE. Vous pouvez le tester dans votre version 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

rendement de sortie:

status  name
12      dbo
0       db_accessadmin
0       db_securityadmin
0       db_ddladmin

aussi via 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

aussi via 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
1
Oleg Melnikov

J'ai une idée que je n'ai pas encore essayée. Tu peux faire:

CREATE VIEW updated_customers AS
SELECT * FROM customer as aa
LEFT JOIN customer_rec as bb
ON aa.id = bb.customer_id
WHERE aa.updated_at between (SELECT start_date FROM config WHERE active = 1) 
and (SELECT end_date FROM config WHERE active = 1)

Vos paramètres seront sauvegardés et modifiés dans le tableau de configuration.

0
Emman