简体   繁体   中英

Execute Stored Procedure in a Cursor

I need to execute stored procedure sp_spaceused for all the tables in my database. I have used cursor for this, please find the below query.The thing is I need to generate report in a single result set. For the below query I'm getting different results.

Declare @Name Varchar(500)
Declare @GetName Cursor
Set     @Getname = Cursor for
select name from sys.tables
Open @Getname
Fetch Next From @Getname into @Name
While @@Fetch_Status=0
Begin
exec sp_spaceused @Name
Fetch Next From @Getname into @Name
End
Close @GetName
Deallocate @GetName

You can use something like the below (the data types may well need tweaking).

Edit: Please see Joe's answer for the correct data types to use!

create table #t
(
name sysname,
rows bigint,
reserved varchar(50),
data varchar(50),
index_size varchar(50),
unused varchar(50)
)

EXEC  sp_MSForEachtable 'insert into #t EXEC sp_spaceused ''?'''

select name,rows,reserved,data,index_size,unused 
from #t
create table #Temp (
    name nvarchar(128),
    [rows] char(11),
    reserved varchar(18),
    data varchar(18),
    index_size varchar(18),
    unused varchar(18)
)

insert into #Temp
    exec sp_msforeachtable 'sp_spaceused [?]'

select * from #Temp

A faster, set-based solution to this problem is to join sys.dm_db_partition_stats and sys.internal_tables, just like sp_spaceused does. The code below is what runs when you generate the "Disk Usage By Table" report in Management Studio.

In my database, the set-based solution returned in 60 ms, while the cursor ran for 22 seconds.

begin try 
SELECT
    (row_number() over(order by a3.name, a2.name))%2 as l1,
    a3.name AS [schemaname],
    a2.name AS [tablename],
    a1.rows as row_count,
    (a1.reserved + ISNULL(a4.reserved,0))* 8 AS reserved, 
    a1.data * 8 AS data,
    (CASE WHEN (a1.used + ISNULL(a4.used,0)) > a1.data THEN (a1.used + ISNULL(a4.used,0)) - a1.data ELSE 0 END) * 8 AS index_size,
    (CASE WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used ELSE 0 END) * 8 AS unused
FROM
    (SELECT 
        ps.object_id,
        SUM (
            CASE
                WHEN (ps.index_id < 2) THEN row_count
                ELSE 0
            END
            ) AS [rows],
        SUM (ps.reserved_page_count) AS reserved,
        SUM (
            CASE
                WHEN (ps.index_id < 2) THEN (ps.in_row_data_page_count + ps.lob_used_page_count + ps.row_overflow_used_page_count)
                ELSE (ps.lob_used_page_count + ps.row_overflow_used_page_count)
            END
            ) AS data,
        SUM (ps.used_page_count) AS used
    FROM sys.dm_db_partition_stats ps
    GROUP BY ps.object_id) AS a1
LEFT OUTER JOIN 
    (SELECT 
        it.parent_id,
        SUM(ps.reserved_page_count) AS reserved,
        SUM(ps.used_page_count) AS used
     FROM sys.dm_db_partition_stats ps
     INNER JOIN sys.internal_tables it ON (it.object_id = ps.object_id)
     WHERE it.internal_type IN (202,204)
     GROUP BY it.parent_id) AS a4 ON (a4.parent_id = a1.object_id)
INNER JOIN sys.all_objects a2  ON ( a1.object_id = a2.object_id ) 
INNER JOIN sys.schemas a3 ON (a2.schema_id = a3.schema_id)
WHERE a2.type <> N'S' and a2.type <> N'IT'
ORDER BY a3.name, a2.name
end try 
begin catch 
select 
    -100 as l1
,   1 as schemaname 
,       ERROR_NUMBER() as tablename
,       ERROR_SEVERITY() as row_count
,       ERROR_STATE() as reserved
,       ERROR_MESSAGE() as data
,       1 as index_size
,       1 as unused 
end catch

Try this:

Create a table (temp or otherwise) that mirrors the result set of the sproc. Then, in the body of your cursor, run this

INSERT INTO <tablename> EXEC sp_spaceused

after you close/deallocate the cursor, select from the table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM