Bru*_*tig 2 sql-server stored-procedures ssms view sql-server-2016
我的问题:我有一组视图,我想从中动态查询。我想将视图名称加载SELECT * from sys.all_views
到游标中(让我们称之为view_cursor
),然后在过程中执行以下操作:
-- loop starts
FETCH NEXT FROM view_cursor INTO @view_name;
SELECT * FROM @view_name;
-- fetch next
-- loop ends
Run Code Online (Sandbox Code Playgroud)
我已经在一个视图中尝试过这个,我将它作为参数传递给存储过程:
CREATE PROCEDURE [dbo].[query_Special_View](@view_name VARCHAR(100)) AS
DECLARE viewname VARCHAR(100);
DECLARE @counter INT = 0;
BEGIN
PRINT @view_name
EXECUTE('SELECT COUNT(Value) INTO' + @counter + 'FROM' + @view_name + '');
PRINT @counter;
END
Run Code Online (Sandbox Code Playgroud)
然后,我想使用现有视图名称执行该过程:
EXEC [dbo].[query_Special_View]
@view_name = N'A_very_special_LOC_view' -- the view name as parameter
GO
Run Code Online (Sandbox Code Playgroud)
结果是:
消息 207,级别 16,状态 1,第 1 行 列名“值”无效。
但是,我尝试COUNT()
在过程中调用该函数的列 Value确实存在。
那么,如何在存储过程中编写这样的动态查询呢?我希望我可以在没有任何丑陋的动态 SQL 魔法的情况下做到这一点,否则我将使用 Java + JDBC 编写我的动态查询逻辑,我可以在其中轻松完成这些事情。
问题与您@counter
在动态 SQL 中的使用有关。它在几个方面是错误的:您想分配给该变量,但在您使用它的地方,它被转换为构建作为 SQL 语句的字符串。您应该改为使用sp_executesql
计数值并将其作为返回参数传回。
我还建议您使用QUOTENAME
来防止语句中的 SQL 注入。如果有人使用精心构造的名称创建视图,他们可能会让您度过非常糟糕的一天。
尝试使用此过程定义:
ALTER PROCEDURE [dbo].[query_Special_View](@schema_name sysname, @view_name sysname) AS
BEGIN
DECLARE @params nvarchar(1000);
DECLARE @sql nvarchar(1000);
DECLARE @return bigint;
SET @params = N'@count bigint OUT';
SET @sql = 'SELECT @count = COUNT(*) FROM ' + QUOTENAME(@schema_name) + '.' + QUOTENAME(@view_name) + ';';
PRINT @sql
EXEC sp_executesql @sql, @params, @count = @return OUT
SELECT SchemaName = @schema_name,
ObjectName = @view_name,
ObjectRowCount = @return
END
GO
Run Code Online (Sandbox Code Playgroud)
对单个调用进行测试就可以正常工作:
EXEC dbo.query_Special_View @schema_name = 'sys', @view_name = 'databases';
Run Code Online (Sandbox Code Playgroud)
您有一系列想要获取行计数的视图。您甚至不需要将其作为存储过程。您可以简单地将这几行代码直接放入游标中并直接执行。
DECLARE @SchemaName sysname,
@ObjectName sysname,
@params nvarchar(1000),
@sql nvarchar(1000),
@return bigint;
--Table to hold the results
CREATE TABLE #Results (
SchemaName sysname,
ObjectName sysname,
ObjectRowCount bigint);
--What objects do you want to get the row counts for?
--I'm just querying sys.views, but edit this query for whatever you need
DECLARE obj_cur CURSOR FOR
SELECT SchemaName = schema_name(schema_id),
ObjectName = name
FROM sys.views v;
--Use that cursor to loop through all objects
OPEN obj_cur;
FETCH NEXT FROM obj_cur INTO @SchemaName, @ObjectName;
WHILE @@FETCH_STATUS = 0
BEGIN
--Dynamic SQL to get the row count
SET @params = N'@count bigint OUT';
SET @sql = 'SELECT @count = COUNT(*) FROM ' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@ObjectName) + ';';
EXEC sp_executesql @sql, @params, @count = @return OUT
--Put that number into a table
INSERT INTO #Results (SchemaName, ObjectName, ObjectRowCount)
SELECT SchemaName = @SchemaName,
ObjectName = @ObjectName,
ObjectRowCount = @return
FETCH NEXT FROM obj_cur INTO @SchemaName, @ObjectName;
END
CLOSE obj_cur;
DEALLOCATE obj_cur;
SELECT *
FROM #Results;
DROP TABLE #Results;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1339 次 |
最近记录: |