我们可以将参数传递给Microsoft SQL Server中的视图吗?
我尝试以下列方式create view
,但它不起作用:
create or replace view v_emp(eno number) as select * from emp where emp_id=&eno;
答案 0 :(得分:113)
如前所述,你做不到。
可能的解决方案是实现存储的函数,例如:
CREATE FUNCTION v_emp (@pintEno INT)
RETURNS TABLE
AS
RETURN
SELECT * FROM emp WHERE emp_id=@pintEno;
这允许您将其用作普通视图,其中包含:
SELECT * FROM v_emp(10)
答案 1 :(得分:31)
有两种方法可以实现你想要的东西,不幸的是,使用视图也无法实现。
您可以创建一个表值用户定义函数,该函数获取您想要的参数并返回查询结果
或者你可以做同样的事情但是创建一个存储过程而不是用户定义的函数。
例如
存储过程看起来像
CREATE PROCEDURE s_emp
(
@enoNumber INT
)
AS
SELECT
*
FROM
emp
WHERE
emp_id=@enoNumber
或者用户定义的函数看起来像
CREATE FUNCTION u_emp
(
@enoNumber INT
)
RETURNS TABLE
AS
RETURN
(
SELECT
*
FROM
emp
WHERE
emp_id=@enoNumber
)
答案 2 :(得分:13)
不,你不能,正如Mladen Prajdic所说。将视图视为表或表组合的“静态过滤器”。例如:视图可以组合表Order
和Customer
,这样您就可以从Order
获得一个新的“行”表以及包含客户名称和客户编号的新列(组合表)。或者您可以创建一个视图,仅从Order
表中选择未处理的订单(静态过滤器)。
然后您可以从视图中选择,就像从任何其他“普通”表中选择一样 - 所有“非静态”过滤必须在视图外部完成(例如“获取客户的所有订单称为Miller”或“获取12月24日发布的未处理订单。)。
答案 3 :(得分:8)
通常情况下,视图不参数化。但你总是可以注入一些参数。例如,使用session context:
sonar.tests=tests_folder
调用:
CREATE VIEW my_view
AS
SELECT *
FROM tab
WHERE num = SESSION_CONTEXT(N'my_num');
另一个:
EXEC sp_set_session_context 'my_num', 1;
SELECT * FROM my_view;
<强> DBFiddle Demo 强>
同样适用于Oracle(当然上下文函数的语法也不同)。
答案 4 :(得分:8)
没有存储过程或函数的hacky方法是在数据库中创建一个设置表,包括列Id,Param1,Param2等。在该表中插入一行,其中包含值Id = 1,Param1 = 0,Param2 = 0等。然后,您可以在视图中为该表添加连接以创建所需的效果,并在运行视图之前更新设置表。如果您有多个用户更新设置表并同时运行视图,则可能会出错,但除此之外它应该可以正常工作。类似的东西:
CREATE VIEW v_emp
AS
SELECT *
FROM emp E
INNER JOIN settings S
ON S.Id = 1 AND E.emp_id = S.Param1
答案 5 :(得分:7)
为什么在视图中需要参数?您可以使用WHERE
子句。
create view v_emp as select * from emp ;
并且您的查询应该完成这项工作:
select * from v_emp where emp_id=&eno;
答案 6 :(得分:6)
没有。 如果必须使用用户定义的函数,可以将参数传递给。
答案 7 :(得分:5)
据我所知,视图可以像select命令一样。 您还可以向此选择添加参数,例如在where语句中添加:
WHERE (exam_id = @var)
答案 8 :(得分:5)
我们可以使用输入参数编写存储过程,然后使用该存储过程从视图中获取结果集。 见下面的例子。
存储过程是
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
和我们可以从中获得结果集的视图是
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%')
答案 9 :(得分:5)
视图只不过是一个预先设定的'SELECT'语句。所以唯一真正的答案是:不,你不能。
我认为你真正想做的是创建一个存储过程,原则上你可以使用任何有效的SQL来做你想做的事情,包括接受参数和选择数据。
当你从视图中选择时,你真的只需要添加一个where子句,但你并没有真正提供足够的细节来确定。
答案 10 :(得分:4)
不,视图是静态的。您可以做的一件事(取决于SQl服务器的版本)是索引视图。
在您的示例中(仅查询一个表),索引视图对于仅使用索引查询表没有任何好处,但如果您在具有连接条件的表上进行大量连接,则索引视图可以大大提高绩效。
答案 11 :(得分:4)
不,查询视图与从表中选择没有什么不同。
要执行您想要的操作,请使用带有一个或多个参数的table-valued user-defined function
答案 12 :(得分:3)
无 您可以将参数传递给视图中的过程
答案 13 :(得分:3)
如果您不想使用某个功能,可以使用类似这样的内容
-- 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
)
希望它会有所帮助
答案 14 :(得分:2)
这是我目前尚未见到的一个选项:
只需将要限制的列添加到视图中:
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)
答案 15 :(得分:1)
你可以绕过只是为了运行视图,SQL会喝酒并哭泣但只是这样做并运行它!你无法保存。
create or replace view v_emp(eno number) as select * from emp where (emp_id = @Parameter1);
答案 16 :(得分:1)
您的视图可以引用一些包含您的参数的外部表。
正如其他人提到的,SQL Server中的视图不能有外部输入参数。但是,您可以使用CTE轻松伪造视图中的变量。您可以在您的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
产出输出:
status name
12 dbo
0 db_accessadmin
0 db_securityadmin
0 db_ddladmin
也可以通过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
也可以通过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
答案 17 :(得分:0)
我有一个尚未尝试的想法。您可以这样做:
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)
您的参数将保存并在Config表中更改。
答案 18 :(得分:0)
我根据我的需要实现了以下任务
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
答案 19 :(得分:0)
答案 20 :(得分:0)
虽然问题得到了很好的回答,但我想补充一点。大多数时候,我们将视图视为发送数据的查询,但视图不仅限于此……视图也可用于更新底层表中的数据。您可以在 SSMS 中右键单击视图,您将找到“编辑前 200 行”选项。
我相信启用这种编辑数据的能力,因为对于如何为 View 编写查询有一定的限制,它需要是一个静态查询。
因此,与发送查询数据并关闭的用户定义函数或存储过程不同,视图可以保持实时连接(例如在 Microsoft Access 链接表/视图中)并将更新写回数据库。
>因此,如果您只想获取一组具有特定动态条件的数据,则应使用带有所需参数的 UDF/SP。