2009-11-06 15 views
76

Czy możemy przekazać parametr do widoku w Microsoft SQL Server?Czy możemy przekazać parametry do widoku w SQL?

Próbowałem create view w następujący sposób, ale to nie działa:

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

Widok jest przechowywany tekst SQL wybranej zapytania. Parametry są poza dyskusją. Kiedy przechowywane zapytanie zwraca kolumnę, w której chcesz filtrować, możesz to zrobić w kwerendzie wywołującej. Na przykład. "WYBIERZ * Z V_emp WHERE emp_id =?" – Epicurist

Odpowiedz

5

nie. , jeśli musisz użyć funkcji zdefiniowanej przez użytkownika, do której możesz przekazywać parametry.

11

Nie, nie możesz, jak powiedział Mladen Prajdic. Traktuj widok jako "filtr statyczny" w tabeli lub kombinacji tabel. Na przykład: widok może łączyć tabele Order i Customer, aby uzyskać nową "tabelę" wierszy od Order wraz z nowymi kolumnami zawierającymi nazwisko klienta i numer klienta (kombinacja tabel). Można również utworzyć widok, który wybiera tylko nieprzetworzone zamówienia z tabeli Order (filtr statyczny).

Wybrałbyś wtedy z widoku tak, jakbyś wybrał inny "normalny" stół - wszystkie "niestatyczne" filtrowanie musi być wykonane poza widokiem (np. "Uzyskaj wszystkie zamówienia dla klientów o nazwie Miller" lub "Uzyskaj nieprzetworzone zamówienia, które pojawiły się 24 grudnia").

24

Istnieją 2 sposoby acheive co chcesz niestety nie można zrobić przy użyciu widoku.

można utworzyć tabelę o wartości zdefiniowanej przez użytkownika funkcji, która pobiera żądany parametr i zwraca wynik zapytania

Albo można zrobić prawie to samo, ale stworzyć procedury przechowywanej zamiast funkcji zdefiniowanych przez użytkownika.

Dla przykładu

procedura przechowywana będzie wyglądać

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

lub funkcja zdefiniowanego przez użytkownika będzie wyglądać

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

nie można przekazać parametr do procedury z punktu widzenia

94

Jak już wspomniano, nie można.

Możliwym rozwiązaniem byłoby zaimplementować funkcję składowaną, jak:

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

To pozwala używać go jako normalnego widoku z:

SELECT * FROM v_emp(10) 
+0

Jakie są praktyczne różnice między tym a widokiem? Czy możesz przypisać uprawnienia użytkownika, aby uzyskać dostęp tylko do tej funkcji? – MikeMurko

+0

W MySQL zapisujesz procedurę przechowywaną i masz ostatnią instrukcję w zestawie, który chcesz zwrócić. – bobobobo

+0

Czy możemy użyć tego żądania bez żadnego problemu z kodu JDBC w java? – mounaim

4

Widok jest niczym więcej niż predefiniowane wyrażenie "SELECT". Tak więc jedyna prawdziwa odpowiedź brzmi: nie, nie możesz.

myślę, co naprawdę chcesz zrobić, to utworzyć procedurę przechowywaną, gdzie w zasadzie można wykorzystać dowolny prawidłowy SQL robić, co chcesz, w tym przyjąć parametry i wybierz dane.

Prawdopodobnie wystarczy dodać klauzulę where, gdy wybierzesz z widoku, ale nie dostarczyłeś wystarczająco dużo szczegółów, aby mieć pewność.

4

Nie, widok jest statyczny. Jedną rzeczą, którą możesz zrobić (w zależności od wersji serwera SQl) jest widok indeksu.

W twoim przykładzie (odpytując tylko jedną tabelę) indeksowany widok nie ma sensu po prostu zapytać o tabelę z indeksem, ale jeśli robisz wiele sprzężeń na tabelach z warunkami łączenia, indeksowany widok może znacznie poprawić wydajność.

4

Możemy napisać procedurę przechowywaną z parametrami wejściowymi, a następnie użyć tej procedury przechowywanej, aby uzyskać zestaw wyników z widoku. patrz przykład poniżej.

procedura przechowywana jest

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 

i widok z którego możemy dostać zestaw wyników jest

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

hacky sposób to zrobić bez procedur składowanych lub funkcji byłoby stworzenie tabele ustawień w bazie danych, z kolumnami Id, Param1, Param2 itd. Wstaw wiersz do tabeli zawierającej wartości Id = 1, Param1 = 0, Param2 = 0, itd. Następnie możesz dodać sprzężenie do tej tabeli w swoim Zobacz, aby utworzyć pożądany efekt i zaktualizuj tabelę ustawień przed uruchomieniem rywalizacji w. Jeśli wielu użytkowników aktualizuje tabelę ustawień i uruchamia widok jednocześnie, wszystko może pójść nie tak, ale w przeciwnym razie powinno działać poprawnie. Coś jak:

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

Tak, masz rację. To okropne rozwiązanie. – Ben

+0

Byłoby strasznie używać go do żądania wyświetlenia. Ale jest naprawdę użyteczne, jako konfiguracja/etap/środowisko, do używania takich ukrytych parametrów. Plus dla mnie za to. – TPAKTOPA

3

Jak wiem, widok może być czymś w rodzaju polecenia polecenia. Można również dodać parametry do tego wyboru na przykład w którym wypowiedzi takie jak ta:

WHERE (exam_id = @var) 
+0

To powinna być akceptowana odpowiedź. Prosto, łatwo i do rzeczy. Wielkie dzięki :) – FrenkyB

5

Dlaczego musisz parametr w widoku? Możesz po prostu użyć klauzuli WHERE.

create view v_emp as select * from emp ; 

i zapytanie należy wykonać zadanie:

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

W niektórych przypadkach nastąpi znaczna poprawa wydajności, gdy jest to "GDZIE" dla tabeli, zamiast "GDZIE" dla widoku. –

3

Jeśli nie chcesz korzystać z funkcji, można użyć coś jak ten

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

nadzieję, że to pomoże

1

Można ominąć, aby uruchomić widok, SQL będzie wina i płakać, ale po prostu zrób to i uruchom! Nie możesz zapisać.

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

Oto opcja nie widziałem do tej pory:

Wystarczy dodać kolumnę, którą chcesz ograniczać się do widzenia:

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

Państwa zdanie może odwoływać się jakiś zewnętrzny tabelę zawierającą twoje parametry.

Jak wspomniano, widok w SQL Server nie może mieć zewnętrznych parametrów wejściowych.Możesz jednak łatwo sfałszować zmienną w widoku za pomocą metody CTE. Możesz przetestować go w swojej wersji 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 

wyjściowy otrzymując:

status name 
12  dbo 
0  db_accessadmin 
0  db_securityadmin 
0  db_ddladmin 

również przez 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 

również przez 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