It's my first question on Stack Overflow; I am facing a problem in changing column names.
I have a table INS_Sink with columns like
INS2017, INS2018, INS2019, INS2020
Now I need to change the existing column names like this:
INS2017 to INS CY-3,
INS2018 to INS CY-2,
INS2019 to INS CY-1,
INS2020 to INS CY,
where CY = CurrentYear.
I need to change all the columns dynamically like the above mentioned and the column names should be changed automatically when the year gets changed like in the year 2021, INS2020 should become INS CY-1..
Can anyone help me how to achieve this and I don't want to alter my columns here?
Thanks in advance...
First, you should not do this. The underlying table should reflect the correct data.
Second, you should not use names like INS CY-1. Such a name needs to be escaped. Instead, you should use INS_CY_1. That is cleaner.
Next, you have a problem with your data model. You should be storing the data as:
YEAR INSVALUE
2017 ?
2018 ?
Of course, you might have other columns that you haven't specified.
With this data structure, it is easy to create a view that does what you want. Say, the current year is found using YEAR(GETDATE()). Then:
select sum(case when t.year = v.yyyy then t.insvalue end) as ins_cy,
sum(case when t.year = v.yyyy - 1 then t.insvalue end) as ins_cy_1,
sum(case when t.year = v.yyyy then t.insvalue end) as ins_cy_2
from t cross join
(values (year(getdate())) v(yyyy);
You can continue this logic for however many years you want to go back in time.
if you really need to get the data in CY-xyz columns then it might be better to create a view and adjust the view when needed (you could use both the view and the table for DML operations).
create table dbo.INS_Sink_test
(
id int identity(1,1) constraint pk_id_ins_sink_test primary key clustered,
col1 int,
col2 int,
INS2010 int,
INS2011 int,
INS2012 int,
INS2013 int,
INS2014 int,
INS2015 int,
INS2016 int,
INS2017 int,
INS2018 int,
INS2019 int,
INS2020 int
)
go
insert into dbo.INS_Sink_test
(
col1, col2, INS2010, INS2011, INS2012, INS2013, INS2014, INS2015, INS2016, INS2017, INS2018, INS2019, INS2020
)
values
(1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4)
go
--create/adjust a view
declare #year smallint = year(getdate());
newyear:
declare #colssql nvarchar(max) = N'';
select #colssql = #colssql + N',' + quotename(name) + ' as ' + quotename(newcolname)
from
(
select column_id,
name,
case when name like 'INS[0-9][0-9][0-9][0-9]' then 'CY' + isnull(cast(nullif(cast(replace(name, 'INS', '') as smallint)-#year, 0) as sysname), '')
else name
end as newcolname
from sys.columns
where object_id = object_id('dbo.INS_Sink_test')
) as a
order by column_id;
declare #viewsql nvarchar(max) = N'view dbo.v_INS_Sink_test
as
select
' + stuff(#colssql, 1, 1, N'') + N'
from dbo.INS_Sink_test
';
select #viewsql = case when object_id('dbo.v_INS_Sink_test') is null then N'create' else N'alter' end + N' ' + #viewsql ;
--print #viewsql
exec(#viewsql);
--dont forget to refresh other views that depend on v_ins_sink_test
--exec sp_refreshview 'dbo.view_xyz';
exec sp_refreshview 'dbo.v_INS_Sink_test';
select #year as theyear;
select *
from dbo.INS_Sink_test;
select *
from dbo.v_INS_Sink_test;
if #year = 2021
begin
--cleanup
if object_id('dbo.INS_Sink_test') is not null
begin
drop table dbo.INS_Sink_test;
end
if object_id('dbo.v_INS_Sink_test') is not null
begin
drop view dbo.v_INS_Sink_test;
end
return;
end
--i know what you did in 2021..
select #year = 2021;
goto newyear
--cleanup
/*
if object_id('dbo.INS_Sink_test') is not null
begin
drop table dbo.INS_Sink_test;
end
if object_id('dbo.v_INS_Sink_test') is not null
begin
drop view dbo.v_INS_Sink_test;
end
*/
For changing the column names of the table:
create table dbo.INS_Sink_test
(
id int identity(1,1) constraint pk_id_ins_sink_test primary key clustered,
col1 int,
col2 int,
INS2010 int,
INS2011 int,
INS2012 int,
INS2013 int,
INS2014 int,
INS2015 int,
INS2016 int,
INS2017 int,
INS2018 int,
INS2019 int,
INS2020 int
)
go
insert into dbo.INS_Sink_test
(
col1, col2, INS2010, INS2011, INS2012, INS2013, INS2014, INS2015, INS2016, INS2017, INS2018, INS2019, INS2020
)
values
(1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4)
go
select *
from dbo.INS_Sink_test
go
--rename columns
declare #year smallint = year(getdate());
declare #renamecolssql nvarchar(max) = N'';
select #renamecolssql = #renamecolssql + N'exec sp_rename ''' + quotename(object_schema_name(object_id)) + N'.' + quotename(object_name(object_id)) + N'.' + quotename(name) + ''', '+ quotename(newcolname) + '; '
from
(
select
object_id,
column_id,
name,
'INS CY' + isnull(cast(nullif(cast(replace(name, 'INS', '') as smallint)-#year, 0) as sysname), '') as newcolname
from sys.columns
where object_id = object_id('dbo.INS_Sink_test') --<-- change the name of the table
and name like 'INS[0-9][0-9][0-9][0-9]'
) as a
order by column_id;
exec(#renamecolssql);
go
select *
from dbo.INS_Sink_test
go
--cleanup
drop table dbo.INS_Sink_test
go
Related
I'm searching but i can't find a solution for my problem.
I've a table (say T1) with this data:
SampleCode
Name
Content
#
1
A#
#
2
B#
#
3
C#
#
1
A#
#
2
B#
#
3
C#
So i need a select query resulting in :
Column 1
Column 2
Column 3
SampleCode
#
#
Name.1
A#
A#
Name.2
B#
B#
Name.3
C#
C#
Does anyone has an hint?
Thanks
Fabio
Check out the 2 options in this article: https://www.sqlshack.com/multiple-options-to-transposing-rows-into-columns/
If using TSQL, you could use a TRANSPOSE statement. Or you can create the result set using cursors/loops and dynamic SQL.
Fully Dynamic Solution
I can't believe I hammered this out... maybe I did it just to see if I could. It's long and complicated and uses several loops. I think you should re-evaluate what you're trying to do. This can't be run in a view. You would have to put into a function or stored procedure. You may want to evaluate the temp table names to see if they are compatible with your environment. Also, since the temp table name are not unique, you cannot run multiple instances; if you want to run multiple instances, you would have to add a unique identifier to a column in the temp tables or to temp table names. This is fully dynamic... you don't have to know how many columns you need ahead of time.
--**************************************************
--Header area... sample data and temp tables.
--**************************************************
--Clean up sample and result tables if they exist.
IF OBJECT_ID(N'tempdb..#T1') IS NOT NULL
DROP TABLE #T1;
IF OBJECT_ID(N'tempdb..#ResultsTemp') IS NOT NULL
DROP TABLE #ResultsTemp;
IF OBJECT_ID(N'tempdb..#codeTable') IS NOT NULL
DROP TABLE #codeTable;
--For Debugging.
DECLARE #debug int = 1; --0=no debug, 1=show debug messages, do not exec all SQL statements.
--Table var to hold sample data.
CREATE TABLE #T1 (
SampleCode nvarchar(50),
[Name] nvarchar(50),
Content nvarchar(50),
row_num int
);
--Load Sample Data.
INSERT INTO #T1 (SampleCode, [Name], Content)
VALUES
('#', '1', 'A#')
, ('#', '2', 'B#')
, ('#', '3', 'C#')
, ('#', '1', 'A#')
, ('#', '2', 'B#')
, ('#', '3', 'C#')
;
--**********END HEADER**********
--Number the rows so we can loop over them.
UPDATE #T1
SET row_num = newT1.row_num
FROM
(
SELECT t12.SampleCode
, t12.[Name]
, T12.Content
, ROW_NUMBER()OVER(ORDER BY SampleCode, [Name], Content) as row_num
FROM #T1 as t12
) AS newT1
WHERE #T1.SampleCode = newT1.SampleCode
AND #T1.[Name] = newT1.[Name]
AND #T1.Content = newT1.Content
;
SELECT * FROM #T1; --Debugging... just show the contents of #T1 after adding row_num
--Create temp table to load results.
CREATE TABLE #ResultsTemp (
Column1 nvarchar(50)
);
--Create some variable to track looping (without a cursor).
DECLARE #loopCount int = 1;
DECLARE #maxLoops int = (SELECT COUNT(DISTINCT SampleCode) FROM #T1);
DECLARE #sql nvarchar(512);
--Add columns to #ResultsTable dynamically
WHILE (#loopCount <= (#maxLoops))
BEGIN
SET #sql = 'ALTER TABLE #ResultsTemp ADD ' + QUOTENAME('Column' + CAST((#loopCount + 1) as nvarchar)) + ' nvarchar(50) NULL';
IF (#debug = 1) PRINT #sql;
EXEC (#sql);
SET #loopCount = #loopCount + 1;
END
--************************************************************
--SECTION FOR INSERTING FIRST ROW for "SampleCode"
--************************************************************
--Vars for tracking the SampleCode variations processed.
DECLARE #sampleLoop int = 1;
DECLARE #sampleCount int = (SELECT COUNT(DISTINCT SampleCode) FROM #T1);
CREATE TABLE #codeTable (
SampleCode nvarchar(50)
, row_num int
);
--Create a list of unique SampleCodes to loop over.
INSERT INTO #codeTable (SampleCode)
SELECT DISTINCT
SampleCode
FROM #T1;
UPDATE #codeTable
SET row_num = newCT.row_num
FROM
(
SELECT ct2.SampleCode
, ROW_NUMBER()OVER(ORDER BY SampleCode) as row_num
FROM #codeTable as ct2
) AS newCT
WHERE #codeTable.SampleCode = newCT.SampleCode
;
SET #sql = 'INSERT INTO #ResultsTemp (Column1) SELECT ''SampleCode''';
IF (#debug = 1) PRINT #sql;
EXEC (#sql);
WHILE (#sampleLoop <= #sampleCount)
BEGIN
SET #sql = 'UPDATE #ResultsTemp SET Column' + CAST(#SampleLoop + 1 as nvarchar) + '=(SELECT TOP 1 SampleCode FROM #codeTable WHERE row_num = ' + CAST(#sampleLoop as nvarchar) + ');';
IF (#debug = 1) PRINT #sql;
EXEC (#sql);
SET #sampleLoop = #sampleLoop + 1;
END
IF (#debug = 1) SELECT * FROM #ResultsTemp;
--**********END SECTION**********
--**************************************************
--SECTION FOR INSERTING THE REST OF THE CONTENT DATA
--**************************************************
--Vars for tracking number of rows processed from T1.
SET #loopCount = 1;
SET #maxLoops = (SELECT MAX(row_num) FROM #T1);
--Loop over each row in T1.
WHILE (#loopCount <= #maxLoops)
BEGIN
--Create a name for this row.
DECLARE #nameRaw nvarchar(50) = (SELECT TOP 1 [Name] FROM #T1 WHERE row_num = #loopCount);
DECLARE #codeNum nvarchar(50) = (
SELECT TOP 1 ct.row_num
FROM #T1 as t
INNER JOIN #codeTable as ct
ON ct.SampleCode = t.SampleCode
WHERE t.row_num = #loopCount);
DECLARE #name nvarchar(50) = 'Name.' + #nameRaw;
--First insert a row for this Name... if not already in the list.
SET #sql = 'INSERT INTO #ResultsTemp (Column1)
SELECT ''Name.'' + t.[Name]
FROM #T1 as t
LEFT OUTER JOIN #ResultsTemp as rt
ON rt.Column1 = ''' + #name + '''
WHERE t.row_num = ' + CAST(#loopCount as nvarchar) + '
AND rt.Column1 IS NULL;';
IF (#debug = 1) PRINT #sql;
EXEC (#sql);
--Update this Name row with the "content".
SET #sql = 'UPDATE rt
SET Column' + CAST(#codeNum + 1 as nvarchar) + '=t.Content
FROM #ResultsTemp as rt
INNER JOIN #T1 as t
ON t.row_num = ' + CAST(#loopCount as nvarchar) + '
AND t.[Name] = ''' + #nameRaw + '''
WHERE rt.Column1 = ''' + #name + ''';';
IF (#debug = 1) PRINT #sql;
EXEC (#sql);
SET #loopCount = #loopCount + 1;
END
--Show everything in the temp Results table.
SELECT *
FROM #ResultsTemp;
Result Set:
Static Select Solution
This next option is not dynamic. You have to know how many columns you need and then you can copy the "Column3" code to any new columns. You have to change the column name and update the "Select TOP 1" statement as commented for each new column you would copy.
WITH CodeTable AS (
SELECT DISTINCT t.SampleCode
FROM #T1 as t
)
SELECT DISTINCT
'Name.' + [Name]
, (
SELECT TOP 1 Content
FROM #T1 as t2
WHERE t2.SampleCode = (
SELECT TOP 1 SampleCode
FROM CodeTable as ct
ORDER BY SampleCode
)
AND t2.[Name] = t.[Name]
) as Column2
, (
SELECT TOP 1 Content
FROM #T1 as t2
WHERE t2.SampleCode = (
SELECT TOP 1 SampleCode
FROM CodeTable as ct
WHERE ct.SampleCode NOT IN (
SELECT TOP 1 SampleCode --Update the TOP 1 to be TOP [number of previous columns]
FROM CodeTable as ct2
ORDER BY ct2.SampleCode
)
ORDER BY ct.SampleCode
)
AND t2.[Name] = t.[Name]
) as Column3
FROM #T1 as t
Static PivotTable Solution
This solution is from the link I posted. Again, you have to know the number of columns you need and it doesn't have generic column names like you specify. But, it is another solution if you reconsider your output.
--Use PivotTable.
SELECT *
FROM
(
SELECT [Name], Content
FROM #T1
) AS SourceTable PIVOT(MAX(Content) FOR [Content] IN([A#],
[A#]
)) AS PivotTable;
Pivot table can solve your prooblem:
DECLARE #T TABLE (SampleCode sysname, Name sysname, Content sysname)
INSERT #T (SampleCode, Name, Content)
VALUES
('#', '1', 'A#'),
('#', '2', 'B#'),
('#', '3', 'C#'),
('#', '1', 'A#'),
('#', '2', 'B#'),
('#', '3', 'C#')
SELECT CONCAT('Name.', PIVOTTABLE.Name), [#], [#]
FROM
(
SELECT * FROM #T AS t
) AS SOURCE
PIVOT (
MAX(Content)
FOR SampleCode IN ([#], [#])
) AS PIVOTTABLE
Of course this is the solution for what you provided in the question.
When the columns are too many to manually write down then use Dynamic query and the only parts needed to be generate is the values in FOR expression and the same value in SELECT
Consider the table in SQL Server 2012
789-0000000
The above number will be consider as a string in SQL Server 2012, but whenever I update the record I need increment to 1.
For example:
When I update the record 1 it should increment to 789-0000001
When I update the record 2 it should increment to 789-0000002
Finally increment should done only 789-0000000
The best solution is to use
an ID INT IDENTITY(1,1) column to get SQL Server to handle the automatic increment of your numeric value
a computed, persisted column to convert that numeric value to the value you need
So try this:
CREATE TABLE dbo.YourTable
(ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
CompanyID AS '789-' + RIGHT('000000' + CAST(ID AS VARCHAR(7)), 7) PERSISTED,
.... your other columns here....
)
Now, every time you insert a row into dbo.YourTable without specifying values for ID or CompanyID:
INSERT INTO dbo.YourTable(Col1, Col2, ..., ColN)
VALUES (Val1, Val2, ....., ValN)
then SQL Server will automatically and safely increase your ID value, and CompanyID will contain values like 789-0000001, 789-0000002,...... and so on - automatically, safely, reliably, no duplicates.
DECLARE #base int = 0
UPDATE TableX
SET
TableX.Value = 'Prefix' + RIGHT('0000000' + CAST(#base AS nvarchar),7),
#base = #base + 1
FROM
TableX
you can split the string
e.g.:
SELECT Item
FROM dbo.SplitString('Apple,Mango,Banana,Guava', ',')
then cast it
e.g.:
SELECT CAST(YourVarcharCol AS INT) FROM Table
then manually increment it
e.g.:
DECLARE max_id INT
SET #max_id = (SELECT MAX(id) FROM source_table)
DECLARE cursor_name CURSOR FOR
SELECT columns, to, copy
FROM source_table
OPEN cursor_name
FETCH NEXT FROM cursor_name
INTO #columns, #to, #cop
at update
e.g.:
declare #i int = SELECT ISNULL(MAX(interfaceID),0) + 1 FROM prices
update prices
set interfaceID = #i , #i = #i + 1
where interfaceID is null
you can understand how complicate this is and why
the solution using a constant to store that prefix is right one.
Declare #str varchar(max) = '789-0000000'
Select
SUBSTRING ( #str ,0 ,CHARINDEX ( '-' ,#str ))
+'-'
+
(SUBSTRING ( #str ,(CHARINDEX ( '-' ,#str)+1) ,(7-LEN(CAST(SUBSTRING ( #str ,CHARINDEX ( '-' ,#str)+1,LEN(#str)) as int))
)
)+
CAST(CAST(SUBSTRING ( #str ,CHARINDEX ( '-' ,#str)+1,LEN(#str)) as int)+1 as varchar))
When #str='789-0001947'
Output #str= 789-0001948
You can write a update trigger on the table with above logic.
I have many (>48) columns in one table, each column corresponds to a month and contains sales for that month. I need to create another table in which each column equals the addition of the previous 12 columns, e.g. getting the "rolling year" figure, so that e.g. July 2010 has everything from August 2009 through July 2010 added, August 2010 has everything from September 2009 through August 2010, and so on.
I could write this as:
select
[201007TOTAL] = [200908] + [200909] + ... + [201007]
,[201008TOTAL] = [200909] + ... + [201008]
...
...
into #newtable
from #mytable
I was wondering if there was a smarter way of doing this, either creating these as new columns in the table in one step, or perhaps pivoting the data, doing something to it, and re-pivoting?
Altough everybody is right, a different database set-up would be best, I thought this was a nice problem to play around with. Here's my setup:
CREATE TABLE TEST
(
ID INT
, [201401] decimal(19, 5)
, [201402] decimal(19, 5)
, [201403] decimal(19, 5)
, [201404] decimal(19, 5)
, [201405] decimal(19, 5)
, [201406] decimal(19, 5)
, [201407] decimal(19, 5)
)
INSERT INTO TEST
VALUES (1, 1, 2, 3, 4, 5, 6, 7)
Just one record with data is enough to test.
On the assumption the columns to be summed are consecutive in the table, and the first one is the first with datatype decimal. In other words, the table 'starts' (for want of better word) with a PK, which is usually INT, may be followed by descriptions or whatever, followed by the monthly columns to be summed:
DECLARE #OP_START INT
, #OP_END INT
, #LOOP INT
, #DATE VARCHAR(255)
, #SQL VARCHAR(MAX) = 'SELECT '
, #COLNAME VARCHAR(MAX)
-- Set Date to max date (=columnname)
SET #DATE = '201406'
-- Find Last attribute
SET #OP_END = (
SELECT MAX(ORDINAL_POSITION)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TEST'
AND COLUMN_NAME <= #DATE
)
-- Find First attribute
SET #OP_START = (
SELECT MIN(ORDINAL_POSITION)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TEST'
AND DATA_TYPE = 'DECIMAL'
)
SET #LOOP = #OP_START
-- Loop through the columns
WHILE #LOOP <= #OP_END
BEGIN
SET #COLNAME = (
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TEST'
AND ORDINAL_POSITION = #LOOP
)
-- Build SQL with found ColumnName
SET #SQL = #SQL + '[' + #COLNAME + ']' + '+'
SET #LOOP = #LOOP + 1
END
-- Remove last "+"
SET #SQL = SUBSTRING(#SQL, 1, LEN(#SQL) - 1)
-- Complete SQL
SET #SQL = #SQL + ' FROM TEST'
-- Execute
EXEC(#SQL)
This should keep adding up the monthly values, regardless how many you add. Just change the max date to what pleases you.
I'm NOT saying this is the best way to go, but it is a fun way :P
I have two variables, 1 varchar named cust_ref, and 1 int named associated_ids. What I'm trying to accomplish is the following:
You provide cust_ref with a value which will usually result in between 1+ rows being returned from the Customer table. I am concerned with gathering all customer_id records for that cust_ref and storing them in the associated_ids variable seperated by commars.
This is the SQL I have so far, and obviously is only loading one of the customer_id records into the variable. Based on this example I would like select #associated_ids to return the following 75458,77397,94955
declare #cust_ref varchar(20) = 'ABGR55532'
declare #associated_ids int
select distinct #associated_ids = customer_id
from dbo.Customer
where cust_ref = #cust_ref
select #associated_ids
select *
from dbo.Customer
where cust_ref = #cust_ref
Here is the results from the above, as you can see there are actually 3 associated_ids that I need stored in the variable in this example but my command is capturing the largest, I want all 3 seperated by commars.
declare #cust_ref varchar(20) = 'ABGR55532' --from your code
DECLARE #result varchar(100)
set #result =
(SELECT distinct (customer_id + ' ')
FROM dbo.Customer
where cust_ref = #cust_ref --from your code
ORDER BY (customer_id + ' ')
FOR XML PATH (''))
SELECT REPLACE(RTRIM(#result),' ',',')
You could try something like this ... obviously, some adjustment will be needed:
create table x (id varchar(50),num int)
insert into x (id,num) values ('75458','20')
insert into x (id,num) values ('77397','20')
insert into x (id,num) values ('94955','20')
and then,
create function GetList (#num as varchar(10))
returns varchar(100)
as
begin
declare #List varchar(100)
select #List = COALESCE(#List + ', ', '') + id
from x
where num = #num
return #List
end
Then, use something like this to get the values:
select distinct num,dbo.GetList(num) from x
Here you go
DECLARE #cust_ref varchar(20) = 'ABGR55532' --from your code
DECLARE #result varchar(100)
set #result =
(SELECT distinct (cast(customer_id as varchar) + ' ')
FROM dbo.Customer
where cust_ref = #cust_ref --from your code
ORDER BY (cast(customer_id as varchar) + ' ')
FOR XML PATH (''))
SELECT REPLACE(RTRIM(#result),' ',',')
How can I determine the space used by a table variable without using DATALENGTH on all columns?
eg:
DECLARE #T TABLE
(
a bigint,
b bigint,
c int,
d varchar(max)
)
insert into #T select 1,2,3, 'abc123'
exec sp_spaceused #T
Trying to work out how much memory a Table variable consumes when running a stored procedure.
I know in this example I can go:
SELECT DATALENGTH(a) + DATALENGTH(b) + DATALENGTH(c) + DATALENGTH(d)
But is there any other way other than doing DATALENGTH on all table columns?
The metadata for table variables is pretty much the same as for other types of tables so you can determine space used by looking in various system views in tempdb.
The main obstacle is that the table variable will be given an auto generated name such as #3D7E1B63 and I'm not sure if there is a straight forward way of determining its object_id.
The code below uses the undocumented %%physloc%% function (requires SQL Server 2008+) to determine a data page belonging to the table variable then DBCC PAGE to get the associated object_id. It then executes code copied directly from the sp_spaceused procedure to return the results.
DECLARE #T TABLE
(
a bigint,
b bigint,
c int,
d varchar(max)
)
insert into #T select 1,2,3, 'abc123'
DECLARE #DynSQL nvarchar(100)
SELECT TOP (1) #DynSQL = 'DBCC PAGE(2,' +
CAST(file_id AS VARCHAR) + ',' +
CAST(page_id AS VARCHAR) + ',1) WITH TABLERESULTS'
FROM #T
CROSS APPLY sys.fn_PhysLocCracker(%%physloc%%)
DECLARE #DBCCPage TABLE (
[ParentObject] [varchar](100) NULL,
[Object] [varchar](100) NULL,
[Field] [varchar](100) NULL,
[VALUE] [varchar](100) NULL
)
INSERT INTO #DBCCPage
EXEC (#DynSQL)
DECLARE #id int
SELECT #id = VALUE
FROM #DBCCPage
WHERE Field = 'Metadata: ObjectId'
EXEC sp_executesql N'
USE tempdb
declare #type character(2) -- The object type.
,#pages bigint -- Working variable for size calc.
,#dbname sysname
,#dbsize bigint
,#logsize bigint
,#reservedpages bigint
,#usedpages bigint
,#rowCount bigint
/*
** Now calculate the summary data.
* Note that LOB Data and Row-overflow Data are counted as Data Pages.
*/
SELECT
#reservedpages = SUM (reserved_page_count),
#usedpages = SUM (used_page_count),
#pages = SUM (
CASE
WHEN (index_id < 2) THEN (in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count)
ELSE lob_used_page_count + row_overflow_used_page_count
END
),
#rowCount = SUM (
CASE
WHEN (index_id < 2) THEN row_count
ELSE 0
END
)
FROM sys.dm_db_partition_stats
WHERE object_id = #id;
/*
** Check if table has XML Indexes or Fulltext Indexes which use internal tables tied to this table
*/
IF (SELECT count(*) FROM sys.internal_tables WHERE parent_id = #id AND internal_type IN (202,204,211,212,213,214,215,216)) > 0
BEGIN
/*
** Now calculate the summary data. Row counts in these internal tables don''t
** contribute towards row count of original table.
*/
SELECT
#reservedpages = #reservedpages + sum(reserved_page_count),
#usedpages = #usedpages + sum(used_page_count)
FROM sys.dm_db_partition_stats p, sys.internal_tables it
WHERE it.parent_id = #id AND it.internal_type IN (202,204,211,212,213,214,215,216) AND p.object_id = it.object_id;
END
SELECT
name = OBJECT_NAME (#id),
rows = convert (char(11), #rowCount),
reserved = LTRIM (STR (#reservedpages * 8, 15, 0) + '' KB''),
data = LTRIM (STR (#pages * 8, 15, 0) + '' KB''),
index_size = LTRIM (STR ((CASE WHEN #usedpages > #pages THEN (#usedpages - #pages) ELSE 0 END) * 8, 15, 0) + '' KB''),
unused = LTRIM (STR ((CASE WHEN #reservedpages > #usedpages THEN (#reservedpages - #usedpages) ELSE 0 END) * 8, 15, 0) + '' KB'')
', N'#id int',#id=#id
Returns
name rows reserved data index_size unused
------------------------------ ----------- ------------------ ------------------ ------------------ ------------------
#451F3D2B 1 16 KB 8 KB 8 KB 0 KB