dub*_*ech 6 sql-server-2008 sql-server stored-procedures
是否可以将表名传入存储过程?
例如,假设您有同一个表的多个视图。它们都具有完全相同的结构。
您需要一个可以为任何视图运行的存储过程。
就像是:
create procedure myprocedure
@tableName varchar(50) = ''
select blah from @tableName where blah = blah2
Run Code Online (Sandbox Code Playgroud)
当我尝试这样做时,我得到
Must declare the table variable @tablename
Run Code Online (Sandbox Code Playgroud)
任何想法我怎么能做到这一点?
Cad*_*oux 11
与其创建视图,不如创建一个内联表值函数——实际上是一个参数化视图。您基本上可以获得视图和参数的所有好处。
您可以在 TVF 中做的另一件事是这样的:
SELECT yourtable.*
FROM yourtable
INNER JOIN ranges
ON yourtable.date BETWEEN ranges.start AND ranges.end
WHERE ranges.name = @range_name
Run Code Online (Sandbox Code Playgroud)
现在您的范围有名称(在一个表中,它们可以在不更改架构的情况下轻松管理) - 这也可以相当无缝地处理具有相同名称的多个范围,尽管如果范围重叠,由于连接匹配两者,您可能会有重复。
另外,请考虑避免 BETWEEN:
我强烈建议您重新考虑您的要求,并且在此处提出问题时,请务必包含更多关于您的动机的信息,因为当您提出问题时对解决方案具有先入为主的概念,您很可能会得到一个次优的解决方案。(就像给定的动态 SQL 解决方案不会轻易适用于您的 OR 案例,但有关问题空间的信息隐藏在您的评论中)
来自:http : //sqlfiddle.com/#!6/a628a/1
CREATE TABLE LogData (
Id INT IDENTITY NOT NULL
,Dt DATETIME NOT NULL
,Data VARCHAR(max) NOT NULL
);
CREATE TABLE Ranges (
Id INT IDENTITY NOT NULL
,Name VARCHAR(50) NOT NULL
,DtStart DATETIME NOT NULL
,DtEnd DATETIME NOT NULL
);
CREATE TABLE Groups (
Id INT IDENTITY NOT NULL
,Name VARCHAR(50) NOT NULL
);
CREATE TABLE RangeGroups (
RangeId INT NOT NULL
,GroupId INT NOT NULL
);
INSERT INTO LogData (Dt, Data)
VALUES ('2011-11-23 11:00', 'before thanksgiving day')
,('2011-11-24 11:00', 'on thanksgiving day')
,('2011-12-24 11:00', 'on christmas eve')
,('2011-12-25 11:00', 'on christmas day')
,('2012-11-21 11:00', 'before thanksgiving day')
,('2012-11-22 11:00', 'on thanksgiving day')
,('2012-12-24 11:00', 'on christmas eve')
,('2012-12-25 11:00', 'on christmas day');
INSERT INTO Ranges (Name, DtStart, DtEnd)
VALUES ('THANKSGIVING2011', '2011-11-24', '2011-11-25')
,('CHRISTMASEVE2011', '2011-12-24', '2011-12-25')
,('CHRISTMASDAY2011', '2011-12-25', '2011-12-26')
,('BOXINGDAY2011', '2011-12-26', '2011-12-27')
,('NEWYEARSEVE2011', '2011-12-31', '2012-01-01')
,('NEWYEARSDAY2012', '2012-01-01', '2012-01-02')
,('THANKSGIVING2012', '2012-11-22', '2012-11-23')
,('CHRISTMASEVE2012', '2012-12-24', '2012-12-25')
,('CHRISTMASDAY2012', '2012-12-25', '2012-12-26')
,('BOXINGDAY2012', '2012-12-26', '2012-12-27')
,('NEWYEARSEVE2012', '2012-12-31', '2013-01-01')
,('NEWYEARSDAY2013', '2013-01-01', '2013-01-02');
INSERT INTO Groups (Name)
VALUES ('HOLIDAYS2011')
,('HOLIDAYS2012')
,('ANYCHRISTMAS');
INSERT INTO RangeGroups (RangeId, GroupId)
SELECT Id, (SELECT Id FROM Groups WHERE Name = 'HOLIDAYS2011')
FROM Ranges WHERE Name LIKE '%2011';
INSERT INTO RangeGroups (RangeId, GroupId)
SELECT Id, (SELECT Id FROM Groups WHERE Name = 'HOLIDAYS2012')
FROM Ranges WHERE Name LIKE '%2012';
INSERT INTO RangeGroups (RangeId, GroupId)
SELECT Id, (SELECT Id FROM Groups WHERE Name = 'ANYCHRISTMAS')
FROM Ranges WHERE Name LIKE 'CHRISTMAS%';
CREATE FUNCTION dbo.JustDoIt(@GroupName VARCHAR(50))
RETURNS TABLE
RETURN (
SELECT LogData.*
FROM LogData
INNER JOIN Ranges ON LogData.Dt >= Ranges.DtStart
AND LogData.Dt < Ranges.DtEnd
INNER JOIN RangeGroups
ON RangeGroups.RangeId = Ranges.Id
INNER JOIN Groups
ON Groups.Id = RangeGroups.GroupId
AND Groups.Name = @GroupName
);
SELECT *
FROM dbo.JustDoIt('HOLIDAYS2011');
SELECT *
FROM dbo.JustDoIt('HOLIDAYS2012');
SELECT *
FROM dbo.JustDoIt('ANYCHRISTMAS');
Run Code Online (Sandbox Code Playgroud)
这部分:
SELECT LogData.*
FROM LogData
INNER JOIN Ranges ON LogData.Dt >= Ranges.DtStart
AND LogData.Dt < Ranges.DtEnd
INNER JOIN RangeGroups
ON RangeGroups.RangeId = Ranges.Id
INNER JOIN Groups
ON Groups.Id = RangeGroups.GroupId
AND Groups.Name = @GroupName
Run Code Online (Sandbox Code Playgroud)
意味着每个日志项都将加入它适合的范围(按日期),每个范围将加入它们所在的组,但只会使用所选的组。
Jon*_*gel 10
对象名称不能参数化。
您需要使用动态 SQL:
CREATE PROCEDURE MyProc
(
@schemaName sysname,
@tableName sysname,
@blah2 int
)
AS
BEGIN
SET NOCOUNT ON
DECLARE @sql nvarchar(MAX)
SET @sql = N'SELECT blah FROM '
+ QUOTENAME(@schemaName) + N'.' + QUOTENAME(@tableName) + N' WHERE blah = @blah2'
EXEC sp_executesql @sql, N'@blah2 int', @blah2
END
Run Code Online (Sandbox Code Playgroud)
请注意,sysname
(当前)定义为nvarchar(128)
.
我认为你最好的选择是使用动态 SQL 来完成这个:
create procedure myprocedure
@tableName nvarchar(50) = ''
as
declare @sql_cmd nvarchar(200)
set @sql_cmd = 'select blah from ' + QUOTENAME(@tableName) + ' where blah = blah2'
exec (@sql_cmd)
go
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
10058 次 |
最近记录: |