Microsoft SQL Server 2005
I almost finished my current C# project where I have created a lot of stored procedures. By a lot I mean almost 200 :) (I know it is a personal feeling :)) Few days ago I was just curious how many lines I wrote in my stored procedures. To satisfy my curiosity I wrote T-SQL code which show me the truth ;)
Blank lines with just Enter pressed are not counted.
Score for my project database is: 142 stored procedures, 9419 lines (most of all 537 lines in one SP)
@ResultType = 0
So what is your best score? ;) How many SPs and lines did you write in your project? :)
Usage: just run below code in context of your current database or use stored procedure
---CODE START HERE---
-- ============================================= -- Author: Marek Sliwinski ( http://binaryelves.wordpress.com ) -- Version: 1.0 -- Create date: 2008-08-08 -- Description: Query to show number of lines in all User stored -- procedures in current database -- Parameters (@ResultType): -- 0 - show number of lines grouped by stored procedure name -- 1 - show total number of lines for all stored procedures -- ============================================= SET NOCOUNT ON; DECLARE @id INT ,@sproc_name NVARCHAR(512) ,@ResultType TINYINT DECLARE @sproc_text TABLE (textline NVARCHAR(MAX) NULL) DECLARE @sproc_container TABLE (textline NVARCHAR(MAX) NULL , sproc_name NVARCHAR(512) NOT NULL) -- ! SET PARAMETER ! -- 0 - show number of lines grouped by stored procedure name -- 1 - show total number of lines for all stored procedures SELECT @ResultType = 1 SELECT @id = min(object_id) FROM sys.procedures WHERE [type] = 'P' AND is_ms_shipped = 0 AND [name] NOT LIKE 'sp[_]%diagram%' WHILE @id IS NOT NULL BEGIN SELECT @sproc_name = [name] FROM sys.procedures WHERE [type] = 'P' AND is_ms_shipped = 0 AND [name] NOT LIKE 'sp[_]%diagram%' AND object_id = @id INSERT INTO @sproc_text EXEC sp_helptext @sproc_name INSERT INTO @sproc_container SELECT * ,@sproc_name FROM @sproc_text DELETE FROM @sproc_text SELECT @id = min(object_id) FROM sys.procedures WHERE [type] = 'P' AND is_ms_shipped = 0 AND [name] NOT LIKE 'sp[_]%diagram%' AND object_id > @id END --remove empty lines, only \r\n DELETE FROM @sproc_container WHERE textline = char(13)+char(10) IF (@ResultType = 1) SELECT COUNT(DISTINCT sproc_name) as NumberOfProcedures ,COUNT(*) as TotalLinesInAllProcedures FROM @sproc_container ELSE IF (@ResultType = 0) SELECT sproc_name as ProcedureName ,COUNT(*) as LinesInProcedure FROM @sproc_container GROUP BY sproc_name ORDER BY LinesInProcedure DESC ,sproc_name ASC ELSE PRINT 'Variable ResultType has to be in: 0,1' ---CODE END HERE---
And below same code but as stored procedure, usage:
exec [custom_ShowNumberOfLinesInSP]
exec [custom_ShowNumberOfLinesInSP] 1
exec [custom_ShowNumberOfLinesInSP] 0
---CODE START HERE---
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Marek Sliwinski ( http://binaryelves.wordpress.com ) -- Version: 1.0 -- Create date: 2008-08-08 -- Description: Query to show number of lines in all User stored -- procedures in current database -- Parameters (@ResultType): -- 0 - show number of lines grouped by stored procedure name -- 1 - show total number of lines for all stored procedures -- ============================================= CREATE PROCEDURE [dbo].[custom_ShowNumberOfLinesInSP] @ResultType TINYINT = 1 AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; DECLARE @id INT ,@sproc_name NVARCHAR(512) DECLARE @sproc_text TABLE (textline NVARCHAR(MAX) NULL) DECLARE @sproc_container TABLE (textline NVARCHAR(MAX) NULL , sproc_name NVARCHAR(512) NOT NULL) SELECT @id = min(object_id) FROM sys.procedures WHERE [type] = 'P' AND is_ms_shipped = 0 AND [name] NOT LIKE 'sp[_]%diagram%' WHILE @id IS NOT NULL BEGIN SELECT @sproc_name = [name] FROM sys.procedures WHERE [type] = 'P' AND is_ms_shipped = 0 AND [name] NOT LIKE 'sp[_]%diagram%' AND object_id = @id INSERT INTO @sproc_text EXEC sp_helptext @sproc_name INSERT INTO @sproc_container SELECT * ,@sproc_name FROM @sproc_text DELETE FROM @sproc_text SELECT @id = min(object_id) FROM sys.procedures WHERE [type] = 'P' AND is_ms_shipped = 0 AND [name] NOT LIKE 'sp[_]%diagram%' AND object_id > @id END --remove empty lines, only \r\n DELETE FROM @sproc_container WHERE textline = char(13)+char(10) IF (@ResultType = 1) SELECT COUNT(DISTINCT sproc_name) as NumberOfProcedures ,COUNT(*) as TotalLinesInAllProcedures FROM @sproc_container ELSE IF (@ResultType = 0) SELECT sproc_name as ProcedureName ,COUNT(*) as LinesInProcedure FROM @sproc_container GROUP BY sproc_name ORDER BY LinesInProcedure DESC ,sproc_name ASC ELSE PRINT 'Variable ResultType has to be in: 0,1' RETURN(0) END ---CODE END HERE---



Very interesting SP.
Good Work!
Pinal Dave ( http://www.SQLAuthority.com )
Thank You! :)
Not sure what is the purpose / use of this SP (I have nothing against your code)
I personally think it would be much more valuable if you could guage the COMPLEXITY of the Stored Procedure based on the CODE which DEV Team can focus on rather them just making any decision based on LINE COUNT
Also, I think many a SP’s have ERROR HANDLERS which can make the LINE COUNT GROW which does not bring any value either
Again I say, I dont see any value add in this (please please dont take it personal)
Hi PP :)
Thx for the comment!
“Not sure what is the purpose / use of this SP
[...]
Again I say, I dont see any value add in this ”
There is only one purpose. The programmer curiosity :) Nothing more.
Have you never wondered about how many lines of SQL you wrote after 4-5 month development in some project? :)
I would like to know the answer because I’m curious man (maybe too much ;))
So there is nothing in code above what you can use to do some technical analysis or improvements in your SQL development (except maybe the thought “100.000 lines in last year? I have to go on holidays IMMEDIATELY!!! ;)) and that wasn’t my goal :)
This particular SP is nothing but for fun. Sorry for confusion if it was not clear enough. It is the same case as for example add-ins for Visual Studio to count number of lines in entire project or solution.
After your post I have started to think what “practical” use can has this SP:
1) maybe analysis which programmer did the most of work in SQL but I don’t think it is a good measure ;)
2) to show the boss that you are not lazy ;) ;)
3) to impress your girlfriend or other friends ;)
4) ? any idea yet? :)
Greetings!
Marek
I came to this site googling to find out how to count number of occurrences within a stored procedure without having a burden to write a SP to do this. I am still searching. But, you can use this query to do line counts without writing a SP. This is not fancy but gives you an idea of line count.
select o.name as sp_name,
sum((len(replace(c.text, char(10), ‘ ‘)) – len(c.text))) as lines_of_code
from sysobjects o
inner join syscomments c
on c.id = o.id
where o.type in (’P', ‘F’)
and o.name not like ’sp_%’
and o.name not like ’sys%’
and o.name not like ‘xp_%’
group by o.name
go
The trick here is to replace CHAR(10) with 2 blanks and count the diff between LEN of the SP code.
Several ways to do same thing. But this is simple and may not be sexy.
I think that I answered my own question by replying to you. If I think about it more. Same query will give count of a keyword in a Stored procedure.
If am trying to count occurrences of CREATE TABLE in a SP, the same query will give me results.
select o.name as sp_name,
sum((len(replace(lower(c.text), ‘create table’, ‘Xcreate table’ ‘)) – len(lower(c.text)))) as lines_of_code
from sysobjects o
inner join syscomments c
on c.id = o.id
where o.type in (’P’, ‘F’)
and o.name not like ’sp_%’
and o.name not like ’sys%’
and o.name not like ‘xp_%’
group by o.name
go
The trick is to replace create table with xcreate_table and count the diff in the count of text and that should give the total number of occurrences.
I try to use SQL as much as possible if I can avoid the SP code. Not that I am averse but we should use engine’s capability and that is where DB2 is way stronger than any other database. My biases – as I am a DB2 person. I am working to move large number of SQL Server / Sybase databases to DB2 and was interested to know complexities involved in SP code.
Hi Vikram :)
Thank you for your interesting comments :)
I didn’t know about syscomments table. It looks like a good and shorter replacment to use instead sp_helptext operations.
But when I did some test procedure like below (with 400 lines of getdate() ) and run your code from 1st post then it returns me only about a half number of lines (201 instead about 400 lines)
So there is something tricky in your SQL statement…
It looks like a problem with stored procedure size. I read that column text in syscomments can take only 4000 chars so maybe here is a point. I don’t have time to investigate this at this moment and will back to this later (maybe you will be faster to solve this problem in your SQL).
Thanks one again for additional idea :) Syscomments table looks better to handle than sp_helptext.
Greetings!
Marek
– TEST SP CODE HERE —
CREATE PROCEDURE [dbo].[TestCountLines]
AS
BEGIN
– SET NOCOUNT ON added to prevent extra result sets from
– interfering with SELECT statements.
SET NOCOUNT ON;
SET DATEFORMAT ymd
SET DATEFIRST 1
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
SELECT getdate()
END