How to get table row count in SQL Server? - sql

There's a requirement where I need to get the table row count information without using count function. Currently I have used the below code to achieve it:
SELECT
CONCAT(schemas.name, '.', tables.name) as tableName,
partitions.rows AS tableRowCount
FROM
sys.partitions
JOIN
sys.tables ON tables.object_id = partitions.object_id
JOIN
sys.schemas ON tables.schema_id = schemas.schema_id
But for some reason, this query is not working properly as expected. Having said that, in some cases tableRowCount is different if the same is checked using the count function.
Is there a way to overcome this challenge?
Please note I tried using sys.dm_db_partition_stats table as well.
However, I get this error:
Msg 104385, Level 16, State 1, Line 9
Catalog view 'dm_db_partition_stats' is not supported in this version.
Please help.

This should be much faster than using COUNT.
SELECT SUM(p.rows) FROM sys.partitions AS p
INNER JOIN sys.tables AS t ON p.[object_id] = t.[object_id]
INNER JOIN sys.schemas AS s ON s.[schema_id] = t.[schema_id]
WHERE t.name = N'(yourtable)' AND s.name = N'dbo' AND p.index_id IN (0,1);
Note that this approach is in no way portable between RDBMSs.

Related

The filegroup cannot be removed because it is not empty Error

I have a file group within a database that has no logical files that cannot be removed. The error message states that the file group is not empty.
I have verified that no partitions exist using the queries below.
SELECT * FROM sys.partition_functions
SELECT * FROM SYS.PARTITION_RANGE_VALUES
SELECT * FROM SYS.PARTITION_SCHEMES
I have also run the queries below in a effort to find anything associated with the file group, but found nothing
SELECT
au.*,
ds.name AS [data_space_name],
ds.type AS [data_space_type],
p.rows,
o.name AS [object_name]
FROM sys.allocation_units au
INNER JOIN sys.data_spaces ds
ON au.data_space_id = ds.data_space_id
INNER JOIN sys.partitions p
ON au.container_id = p.partition_id
INNER JOIN sys.objects o
ON p.object_id = o.object_id
ORDER BY ds.name;
SELECT *
FROM sys.filegroups fg
LEFT OUTER JOIN sysfilegroups sfg
ON fg.name = sfg.groupname
LEFT OUTER JOIN sysfiles f
ON sfg.groupid = f.groupid
LEFT OUTER JOIN sys.allocation_units i
ON fg.data_space_id = i.data_space_id
WHERE i.data_space_id IS NULL;
select * from sys.allocation_units
where data_space_id = (select data_space_id from sys.data_spaces where name = 'HL7');
In addition, I have been able to backup the database and restore to a different SQL Server and duplicate this problem.
What else can be checked to find out what is preventing the file group from being removed?
I had a similar situation recently. I ran
DBCC SHRINKFILE (N'myfile', EMPTYFILE)
after which I was able to remove the file.
Frankly I didn't expect it to work, since in my case the filegroup has no other files in it. So even though the operation should
Migrates all data from the specified file to other files in the same
filegroup
There was no file to migrate the data to. But it worked! No errors or warnings. Right after I removed the file without issue. Guessing that there was some messed up entries that bothered REMOVE FILE but not SHRINKFILE.
Give it a go and post your results here.

Find all Tables that contain Column Name; Filter Empties

I've been using the SQL found here:
Find all tables containing column with specified name
to great success. It allows me to find all tables that contain a certain column. My issue is that the database I'm working on seems to have a lot of empty tables (maybe around half of my results are empties). I was wondering if there was a way to modify the code in the link such that empty rows/columns are not presented.Below is the code from the link:
SELECT c.name AS 'ColumnName'
,t.name AS 'TableName'
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE c.name LIKE '%MyName%'
ORDER BY TableName
,ColumnName;
Thank you,
Something like this may work without huge effort:
SELECT c.name AS 'ColumnName'
,t.name AS 'TableName'
,p.rows
FROM sys.columns c
INNER JOIN sys.tables t
ON c.object_id = t.object_id
INNER JOIN sys.partitions p
on t.object_id = p.object_id
WHERE c.name LIKE '%p%'
AND p.rows > 0
ORDER BY TableName
,ColumnName;
Just note that sys.partitions isn't guaranteed to be accurate about row counts; sys.dm_db_index_physical_stats may be better (see https://dba.stackexchange.com/questions/55124/how-accurate-is-the-sys-partition-rows-column). This might give you a better count but may have more locking issues if you're using AlwaysOn:
SELECT c.name AS 'ColumnName'
,t.name AS 'TableName'
,ips.record_count
FROM sys.columns c
INNER JOIN sys.tables t
ON c.object_id = t.object_id
CROSS APPLY sys.dm_db_index_physical_stats(DB_ID(), t.object_id, null, null, 'DETAILED') ips
WHERE c.name LIKE '%p%'
AND ips.record_count > 0
ORDER BY TableName
,ColumnName;
If you really need 100% reliability on this, you'd have actually do a COUNT(*) on each table (using Dynamic SQL) you want to check, but this is probably good enough.

sys.syscomments.name length > 4,000

The code below displays, among other things, the source code for all the triggers in a database
SELECT so.name AS trigger_name,
s.name AS table_schema,
t.name AS table_name,
LEN (sc.[text]) as len,
sc.[text] AS trigger_content
FROM [GDI-193-DEV].dbo.sysobjects so
INNER JOIN [GDI-193-DEV].sys.tables t ON so.parent_obj = t.object_id
INNER JOIN [GDI-193-DEV].sys.schemas s ON t.schema_id = s.schema_id
INNER JOIN [GDI-193-DEV].sys.syscomments sc ON so.id = sc.id
WHERE so.type = 'TR'
The problem is if the length of the trigger source code is more than 4,000 characters it ends up spanning two records in sys.syscomments.
So, for example, if the trigger source is 4,700 characters it will be spread across 2 records in sys.syscomments. sys.syscomments.TEXT in the first record will have a length of 4,000 while the remaining 700 characters will be put into another record.
This is causing problems for me as I am trying to compare the complete trigger source code between two databases.
This seem like some strange behavior. Am I missing something? Is there a different way of getting the source code that avoids this problem?
Thanks in advance,
I had the same problem, and found out that there's another way to get untrimmed definitions. Try if entire code of your trigger shows, and then you can work your way to joinning this to other system tables/views:
select top 100
*
from sys.sql_modules
where 1=1
and definition like '%trigger%'
Try using object_definition like this:
SELECT so.name AS trigger_name,
s.name AS table_schema,
t.name AS table_name,
object_definition(so.object_id) AS trigger_content
FROM [GDI-193-DEV].dbo.sysobjects so
INNER JOIN [GDI-193-DEV].sys.tables t ON so.parent_obj = t.object_id
INNER JOIN [GDI-193-DEV].sys.schemas s ON t.schema_id = s.schema_id
WHERE so.type = 'TR'

How to discover trigger's parent schema?

To discover all triggers in any given MS SQL Server database, I'm currently querying the sysobjects table (which is fine because it works in MS SQL Server 2000 which I have to support) e.g.
SELECT R1.name AS trigger_name,
T1.name AS trigger_parent_table_name
FROM sysobjects AS R1
INNER join sysobjects AS T1
ON R1.parent_obj = T1.id
WHERE R1.xtype = 'tr';
This gives me a reduced list of trigger names and for each I can use
EXEC sp_helptext 'trigger_name_here'
to find the definition. That works fine for databases where only the default dbo schema is used.
I now have a MS SQL Server 2005 database which uses multiple schemas. What is the best way of discovering the schema for each trigger?
You are looking for the parent object for a trigger so it will always be a table. In sys.tables (system view) you get the schema_id and with it you can go sys.schemas (system view too) to get the schema's name.
Hope this helps.
--
EDIT:
The code:
SELECT sys.objects.name AS [trigger],
sys.tables.name AS [table],
sys.objects.type,
sys.schemas.name AS [schema]
FROM sys.schemas RIGHT OUTER JOIN
sys.tables ON sys.schemas.schema_id = sys.tables.schema_id RIGHT OUTER JOIN
sys.objects ON sys.tables.object_id = sys.objects.parent_object_id
WHERE sys.objects.type = 'tr'
This is is with sys.tables but you can do it with only sys.objects, this is a general select to look for parents and schemas:
SELECT O.name, O.type, S.name AS [schema],
OP.name AS parent_name, OP.type AS parent_type, SP.name AS parent_schema
FROM sys.schemas AS SP RIGHT OUTER JOIN
sys.objects AS OP ON SP.schema_id = OP.schema_id RIGHT OUTER JOIN
sys.objects AS O LEFT OUTER JOIN
sys.schemas AS S ON O.schema_id = S.schema_id ON OP.object_id = O.parent_object_id

List of Stored Procedure from Table

I have a huge database with 100's of tables and stored procedures. Using SQL Server 2005, how can I get a list of stored procedures that are doing an insert or update operation on a given table.
sys.sql_dependencies has a list of entities with dependencies, including tables and columns that a sproc includes in queries. See this post for an example of a query that gets out dependencies. The code snippet below will get a list of table/column dependencies by stored procedure
select sp.name as sproc_name
,t.name as table_name
,c.name as column_name
from sys.sql_dependencies d
join sys.objects t
on t.object_id = d.referenced_major_id
join sys.objects sp
on sp.object_id = d.object_id
join sys.columns c
on c.object_id = t.object_id
and c.column_id = d.referenced_minor_id
where sp.type = 'P'
select
so.name,
sc.text
from
sysobjects so inner join syscomments sc on so.id = sc.id
where
sc.text like '%INSERT INTO xyz%'
or sc.text like '%UPDATE xyz%'
This will give you a list of all stored procedure contents with INSERT or UPDATE in them for a particular table (you can obviously tweak the query to suit). Also longer procedures will be broken across multiple rows in the returned recordset so you may need to do a bit of manual sifting through the results.
Edit: Tweaked query to return SP name as well. Also, note the above query will return any UDFs as well as SPs.
Use sys.dm_sql_referencing_entities
Note that sp_depends is obsoleted.
MSDN Reference
You could try exporting all of your stored procedures into a text file and then use a simple search.
A more advanced technique would be to use a regexp search to find all SELECT FROM and INSERT FROM entries.
If you download sp_search_code from Vyaskn's website it will allow you to find any text within your database objects.
http://vyaskn.tripod.com/sql_server_search_stored_procedure_code.htm
This seems to work:
select
so.name as [proc],
so2.name as [table],
sd.is_updated
from sysobjects so
inner join sys.sql_dependencies sd on so.id = sd.object_id
inner join sysobjects so2 on sd.referenced_major_id = so2.id
where so.xtype = 'p' -- procedure
and is_updated = 1 -- proc updates table, or at least, I think that's what this means
SELECT Distinct SO.Name
FROM sysobjects SO (NOLOCK)
INNER JOIN syscomments SC (NOLOCK) on SO.Id = SC.ID
AND SO.Type = 'P'
AND (SC.Text LIKE '%UPDATE%' OR SC.Text LIKE '%INSERT%')
ORDER BY SO.Name
This link was used as a resource for the SP search.