Chúng ta có thể truyền tham số cho chế độ xem trong Microsoft SQL Server không?
Tôi đã cố gắng create view
theo cách sau, nhưng nó không hoạt động:
create or replace view v_emp(eno number) as select * from emp where emp_id=&eno;
Chúng ta có thể truyền tham số cho chế độ xem trong Microsoft SQL Server không?
Tôi đã cố gắng create view
theo cách sau, nhưng nó không hoạt động:
create or replace view v_emp(eno number) as select * from emp where emp_id=&eno;
Câu trả lời:
Như đã nêu bạn không thể.
Một giải pháp khả thi sẽ là thực hiện một chức năng được lưu trữ, như:
CREATE FUNCTION v_emp (@pintEno INT)
RETURNS TABLE
AS
RETURN
SELECT * FROM emp WHERE emp_id=@pintEno;
Điều này cho phép bạn sử dụng nó như một chế độ xem bình thường, với:
SELECT * FROM v_emp(10)
Có 2 cách để đạt được điều bạn muốn một cách đáng tiếc, không thể thực hiện được bằng cách sử dụng chế độ xem.
Bạn có thể tạo một hàm có giá trị do người dùng định nghĩa bảng lấy tham số bạn muốn và trả về kết quả truy vấn
Hoặc bạn có thể làm khá nhiều thứ tương tự nhưng tạo một thủ tục được lưu trữ thay vì hàm do người dùng xác định.
Ví dụ
thủ tục lưu trữ sẽ trông như thế nào
CREATE PROCEDURE s_emp
(
@enoNumber INT
)
AS
SELECT
*
FROM
emp
WHERE
emp_id=@enoNumber
Hoặc chức năng do người dùng xác định sẽ trông như thế nào
CREATE FUNCTION u_emp
(
@enoNumber INT
)
RETURNS TABLE
AS
RETURN
(
SELECT
*
FROM
emp
WHERE
emp_id=@enoNumber
)
Không, bạn không thể, như Mladen Prajdic nói. Hãy nghĩ về một khung nhìn như một "bộ lọc tĩnh" trên một bảng hoặc một tổ hợp các bảng. Ví dụ: một chế độ xem có thể kết hợp các bảng Order
và Customer
do đó bạn có được một "bảng" hàng Order
mới cùng với các cột mới chứa tên của khách hàng và số khách hàng (kết hợp các bảng). Hoặc bạn có thể tạo chế độ xem chỉ chọn các đơn đặt hàng chưa được xử lý từ Order
bảng (bộ lọc tĩnh).
Sau đó, bạn sẽ chọn từ chế độ xem như bạn sẽ chọn từ bất kỳ bảng "bình thường" nào khác - tất cả quá trình lọc "không tĩnh" phải được thực hiện ngoài chế độ xem (như "Nhận tất cả các đơn đặt hàng cho khách hàng được gọi là Miller" hoặc "Nhận đơn đặt hàng chưa xử lý đã đến vào ngày 24 tháng 12 ").
Thông thường các khung nhìn không được tham số hóa. Nhưng bạn luôn có thể tiêm một số thông số. Ví dụ: sử dụng bối cảnh phiên :
CREATE VIEW my_view
AS
SELECT *
FROM tab
WHERE num = SESSION_CONTEXT(N'my_num');
Cầu nguyện:
EXEC sp_set_session_context 'my_num', 1;
SELECT * FROM my_view;
Và một cái khác:
EXEC sp_set_session_context 'my_num', 2;
SELECT * FROM my_view;
Điều tương tự cũng được áp dụng cho Oracle (tất nhiên cú pháp cho chức năng ngữ cảnh là khác nhau).
Tại sao bạn cần một tham số trong xem? Bạn chỉ có thể sử dụng WHERE
mệnh đề.
create view v_emp as select * from emp ;
và truy vấn của bạn sẽ thực hiện công việc:
select * from v_emp where emp_id=&eno;
WHERE
cho bảng, thay vì WHERE
cho chế độ xem.
Một cách khó khăn để làm điều đó mà không có các thủ tục hoặc hàm được lưu trữ sẽ là tạo một bảng cài đặt trong cơ sở dữ liệu của bạn, với các cột Id, Param1, Param2, v.v. Chèn một hàng vào bảng đó chứa các giá trị Id = 1, Param1 = 0, Param2 = 0, v.v. Sau đó, bạn có thể thêm một liên kết vào bảng đó trong chế độ xem của mình để tạo hiệu ứng mong muốn và cập nhật bảng cài đặt trước khi chạy chế độ xem. Nếu bạn có nhiều người dùng cập nhật bảng cài đặt và chạy chế độ xem đồng thời, mọi thứ có thể bị lỗi, nhưng nếu không thì nó sẽ hoạt động tốt. Cái gì đó như:
CREATE VIEW v_emp
AS
SELECT *
FROM emp E
INNER JOIN settings S
ON S.Id = 1 AND E.emp_id = S.Param1
Không. nếu sau đó bạn phải sử dụng hàm do người dùng xác định mà bạn có thể truyền tham số vào.
Không, một khung nhìn được truy vấn không khác với CHỌN từ bảng.
Để làm những gì bạn muốn, hãy sử dụng hàm do người dùng xác định có giá trị bảng với một hoặc nhiều tham số
Một khung nhìn không có gì khác hơn là một tuyên bố 'CHỌN' được xác định trước. Vì vậy, câu trả lời thực sự duy nhất sẽ là: Không, bạn không thể.
Tôi nghĩ rằng những gì bạn thực sự muốn làm là tạo một thủ tục được lưu trữ, theo nguyên tắc bạn có thể sử dụng bất kỳ SQL hợp lệ nào để làm bất cứ điều gì bạn muốn, bao gồm chấp nhận tham số và chọn dữ liệu.
Có vẻ như bạn thực sự chỉ cần thêm một mệnh đề where khi bạn chọn từ chế độ xem của mình, nhưng bạn không thực sự cung cấp đủ chi tiết để chắc chắn.
chúng ta có thể viết một thủ tục được lưu trữ với các tham số đầu vào và sau đó sử dụng thủ tục được lưu trữ đó để lấy tập kết quả từ khung nhìn. xem ví dụ dưới đây.
thủ tục lưu trữ là
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
và khung nhìn từ đó chúng ta có thể nhận được tập kết quả là
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%')
Không, một cái nhìn là tĩnh. Một điều bạn có thể làm (tùy thuộc vào phiên bản của máy chủ SQl) là lập chỉ mục một chế độ xem.
Trong ví dụ của bạn (chỉ truy vấn một bảng), chế độ xem được lập chỉ mục không có lợi khi chỉ truy vấn bảng có chỉ mục trên đó, nhưng nếu bạn thực hiện nhiều phép nối trên bảng có điều kiện nối, thì chế độ xem được lập chỉ mục có thể cải thiện hiệu suất rất nhiều.
Nếu bạn không muốn sử dụng một chức năng, bạn có thể sử dụng một cái gì đó như thế này
-- 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
)
Hy vọng nó sẽ giúp
Đây là một tùy chọn tôi chưa thấy cho đến nay:
Chỉ cần thêm cột bạn muốn hạn chế vào chế độ xem:
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)
Bạn có thể bỏ qua chỉ để chạy view, SQL sẽ khóc và khóc nhưng chỉ cần làm điều này và chạy nó! Bạn không thể tiết kiệm.
create or replace view v_emp(eno number) as select * from emp where (emp_id = @Parameter1);
Khung nhìn của bạn có thể tham chiếu một số bảng bên ngoài có chứa các tham số của bạn.
Như những người khác đã đề cập, khung nhìn trong SQL Server không thể có các tham số đầu vào bên ngoài. Tuy nhiên, bạn có thể dễ dàng giả mạo một biến trong chế độ xem của mình bằng CTE. Bạn có thể chạy thử nó trong phiên bản SQL Server của bạn.
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
mang lại sản lượng:
status name
12 dbo
0 db_accessadmin
0 db_securityadmin
0 db_ddladmin
cũng thông qua 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
cũng thông qua 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
Tôi có một ý tưởng mà tôi chưa thử. Bạn có thể làm:
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)
Các tham số của bạn sẽ được lưu và thay đổi trong bảng Cấu hình.
Tôi nhận ra nhiệm vụ này cho nhu cầu của mình như sau
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