Czy możemy przekazać parametr do widoku w Microsoft SQL Server?
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;
sql
sql-server
parameters
parameter-passing
views
arunachalam
źródło
źródło
Parameters are out of the discussion
Zbyt odważne stwierdzenie. CounterexampleOdpowiedzi:
Jak już wspomniano, nie możesz.
Możliwym rozwiązaniem byłoby zaimplementowanie przechowywanej funkcji, takiej jak:
CREATE FUNCTION v_emp (@pintEno INT) RETURNS TABLE AS RETURN SELECT * FROM emp WHERE emp_id=@pintEno;
Pozwala to używać go jako normalnego widoku, z:
SELECT * FROM v_emp(10)
źródło
Niestety, istnieją 2 sposoby osiągnięcia tego, co chcesz, ale nie można tego zrobić za pomocą widoku.
Możesz utworzyć funkcję zdefiniowaną przez użytkownika z wartościami tabeli, która przyjmuje żądany parametr i zwraca wynik zapytania
Lub możesz zrobić prawie to samo, ale utworzyć procedurę składowaną zamiast funkcji zdefiniowanej przez użytkownika.
Na przykład
jak wyglądałaby procedura składowana
CREATE PROCEDURE s_emp ( @enoNumber INT ) AS SELECT * FROM emp WHERE emp_id=@enoNumber
Albo jak wyglądałaby funkcja zdefiniowana przez użytkownika
CREATE FUNCTION u_emp ( @enoNumber INT ) RETURNS TABLE AS RETURN ( SELECT * FROM emp WHERE emp_id=@enoNumber )
źródło
SELECT
: przeczytaj więcej .Nie, nie możesz, jak powiedział Mladen Prajdic. Pomyśl o widoku jako o „filtrze statycznym” tabeli lub kombinacji tabel. Na przykład: widok może łączyć tabele
Order
iCustomer
tak pojawi się nowy „stół” z wierszyOrder
wraz z nowymi kolumnami zawierającymi nazwę klienta i numer klienta (połączenie tabel). Możesz też utworzyć widok, który wybiera tylko nieprzetworzone zamówienia zOrder
tabeli (filtr statyczny).Następnie wybierzesz z widoku, tak jak w przypadku każdej innej „normalnej” tabeli - wszystkie „niestatyczne” filtrowanie należy wykonać poza widokiem (np. „Pobierz wszystkie zamówienia dla klientów o nazwie Miller” lub „Otrzymuj nieprzetworzone zamówienia które nadeszło 24 grudnia ”).
źródło
Zwykle widoki nie są sparametryzowane. Ale zawsze możesz wprowadzić jakieś parametry. Na przykład używając kontekstu sesji :
CREATE VIEW my_view AS SELECT * FROM tab WHERE num = SESSION_CONTEXT(N'my_num');
Wezwanie:
EXEC sp_set_session_context 'my_num', 1; SELECT * FROM my_view;
I kolejny:
EXEC sp_set_session_context 'my_num', 2; SELECT * FROM my_view;
DBFiddle Demo
To samo dotyczy Oracle (oczywiście składnia funkcji kontekstu jest inna).
źródło
Dlaczego potrzebujesz widoku parametru? Możesz po prostu użyć
WHERE
klauzuli.create view v_emp as select * from emp ;
a twoje zapytanie powinno załatwić sprawę:
select * from v_emp where emp_id=&eno;
źródło
WHERE
dla tabeli, zamiastWHERE
dla widoku.Hackim sposobem na zrobienie tego bez procedur składowanych lub funkcji byłoby utworzenie tabeli ustawień w bazie danych z kolumnami Id, Param1, Param2 itd. Wstaw wiersz do tej tabeli zawierający wartości Id = 1, Param1 = 0, Param2 = 0 itd. Następnie możesz dodać sprzężenie do tej tabeli w swoim widoku, aby uzyskać pożądany efekt, i zaktualizować tabelę ustawień przed uruchomieniem widoku. Jeśli masz wielu użytkowników aktualizujących tabelę ustawień i uruchamiających widok jednocześnie, rzeczy mogą pójść nie tak, ale poza tym 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
źródło
Nie. jeśli musisz użyć funkcji zdefiniowanej przez użytkownika, do której możesz przekazać parametry.
źródło
Nie, odpytywanie widoku nie różni się od wyboru z tabeli.
Aby zrobić to, co chcesz, użyj funkcji zdefiniowanej przez użytkownika z wartościami przechowywanymi w tabeli z co najmniej jednym parametrem
źródło
Widok to nic innego jak predefiniowana instrukcja „SELECT”. Tak więc jedyną prawdziwą odpowiedzią byłoby: Nie, nie możesz.
Myślę, że to, co naprawdę chcesz zrobić, to utworzyć procedurę składowaną, w której w zasadzie możesz użyć dowolnego prawidłowego kodu SQL, aby zrobić, co chcesz, w tym zaakceptować parametry i wybrać dane.
Wydaje się prawdopodobne, że naprawdę wystarczy dodać klauzulę WHERE tylko podczas wybierania z widoku, ale tak naprawdę nie podałeś wystarczająco dużo szczegółów, aby mieć pewność.
źródło
możemy napisać procedurę składowaną z parametrami wejściowymi, a następnie użyć tej procedury składowanej, aby uzyskać zestaw wyników z widoku. patrz przykład poniżej.
procedura składowana to
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
a widok, z którego możemy uzyskać zbiór wyników, to
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%')
źródło
Jak wiem, widok może być czymś w rodzaju polecenia wyboru. Możesz również dodać parametry do tego wyboru, na przykład w przypadku takich instrukcji:
źródło
Nie, widok jest statyczny. Jedną rzeczą, którą możesz zrobić (w zależności od wersji serwera SQl), jest zindeksowanie widoku.
W Twoim przykładzie (odpytywanie tylko jednej tabeli) widok indeksowany nie daje korzyści z prostego wysyłania zapytań do tabeli z indeksem, ale jeśli wykonujesz wiele sprzężeń w tabelach z warunkami łączenia, widok indeksowany może znacznie poprawić wydajność.
źródło
Jeśli nie chcesz używać funkcji, możesz użyć czegoś takiego
-- 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 )
Mam nadzieję, że to pomoże
źródło
nie, możesz przekazać parametr do wyświetlanej procedury
źródło
Oto opcja, której do tej pory nie widziałem:
Po prostu dodaj kolumnę, którą chcesz ograniczyć do widoku:
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)
źródło
Możesz ominąć tylko po to, aby uruchomić widok, SQL będzie płakać i płakać, ale po prostu zrób to i uruchom! Nie możesz uratować.
create or replace view v_emp(eno number) as select * from emp where (emp_id = @Parameter1);
źródło
Twój widok może odnosić się do zewnętrznej tabeli zawierającej twoje parametry.
Jak wspominali inni, widok w SQL Server nie może mieć zewnętrznych parametrów wejściowych. Możesz jednak łatwo sfałszować zmienną w swoim widoku za pomocą CTE. Możesz go przetestować 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
wydajność:
również za pośrednictwem
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ż za pośrednictwem
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
źródło
Mam pomysł, którego jeszcze nie próbowałem. Możesz to zrobić:
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)
Twoje parametry zostaną zapisane i zmienione w tabeli konfiguracji.
źródło
Zrealizowałem to zadanie dla moich potrzeb w następujący sposób
set nocount on; declare @ToDate date = dateadd(month,datediff(month,0,getdate())-1,0) declare @year varchar(4) = year(@ToDate) declare @month varchar(2) = month(@ToDate) declare @sql nvarchar(max) set @sql = N' create or alter view dbo.wTempLogs as select * from dbo.y2019 where year(LogDate) = ''_year_'' and month(LogDate) = ''_month_'' ' select @sql = replace(replace(@sql,'_year_',@year),'_month_',@month) execute sp_executesql @sql declare @errmsg nvarchar(max) set @errMsg = @sql raiserror (@errMsg, 0,1) with nowait
źródło
Po prostu użyj tego widoku do procedury składowanej z wymaganymi parametrami (np. W SQL Server) i wartościami parametrów w widoku zapytań.
Utwórz procedurę składowaną za pomocą View / table: _spCallViewWithParameters
Wykonaj procedurę:
źródło