Posts Tagged ‘tsql’

Generate random integers using tsql UDFs

Ever need to generate random numbers from the integer family?  I had this need on a project so I whipped up these four tsql User Defined Functions to help with this task.  There are four functions in all, one for tinyint, smallint, int, and bigint.  Additionally, you will need to create one VIEW since you can not fire the tsql function RAND() inside of a udf.

With these functions, you can generate random integers in their native range.

 SELECT dbo.getRandomInt( NULL, NULL ) 

Or you can restrict your random integers to a range of your liking.

 SELECT dbo.getRandomInt( 1000, 1000000000) 

Just as a reminder, here are the native ranges for these four integer types as supported by MS SQL Server 2005

bigint -2^63 (-9,223,372,036,854,775,808) to 2^63-1 (9,223,372,036,854,775,807)
int -2^31 (-2,147,483,648) to 2^31-1 (2,147,483,647)
smallint -2^15 (-32,768) to 2^15-1 (32,767)
tinyint 0 to 255

Each of these functions have the same structure and primarily differ only by the integer type’s native range.  Here is the guts of one of the UDFs in case you want just the facts.

/******************************************************************************
Generate a random int
-------------------------------------------------------------------------------
USAGE :
 -- Get random int in the default range -2,147,483,648 to 2,147,483,647
 SELECT dbo.getRandomInt( NULL, NULL )

 -- Get random tinyint within a specific range
 SELECT dbo.getRandomInt( 1000, 30000 )

REQUIREMENT : Since you can't call RAND() inside of a UDF,
this function is dependant on the following VIEW vRand :

-- BEGIN VIEW
 -- This is only a helper VIEW since currently you can not use RAND() in a UDF
 -- DROP VIEW vRand
 CREATE VIEW [dbo].[vRand]
 AS
 SELECT RAND() AS 'number'
-- END VIEW

******************************************************************************/

USE SmartEarth
GO

IF OBJECT_ID (N'getRandomInt') IS NOT NULL
 DROP FUNCTION getRandomInt
GO

CREATE FUNCTION getRandomInt( @min_in int, @max_in int )
RETURNS int
WITH EXECUTE AS CALLER
AS
BEGIN
-------------------------------------------------------------------------------
 DECLARE @max int,
 @min int,
 @rand NUMERIC( 18,10 ),
 @max_big NUMERIC( 38, 0 ),
 @rand_num NUMERIC( 38, 0 ),
 @out int;

 -- define this datatype's natural range
 SET @min = -2147483648    -- -2,147,483,648
 SET @max = 2147483647    -- 2,147,483,647

 -- Check to see if a range has been passed in.
 -- Otherwise, set to default tinyint range
 IF( @min_in is not null AND @min_in > @min )
 SET @min = @min_in

 IF( @max_in is not null AND @max_in < @max )
 SET @max = @max_in
 -- end range check

 -- get RAND() from VIEW since we can't use it in UDF
 SELECT @rand = number FROM vRand

 -- CAST @max so the number generation doesn't overflow
 SET @max_big = CAST( @max AS NUMERIC(38,0) )

 -- make the number
 SELECT @rand_num = ( (@max_big + 1) - @min ) * @rand + @min;

 -- validate rand
 IF( @rand_num > @max )
 -- too big
 SET @out = @max
 ELSE IF ( @rand_num < @min )
 -- too small
 SET @out = @min
 ELSE
 -- just right, CAST it
 SET @out = CAST( @rand_num AS int )

 -- debug
 -- SELECT @min_in AS 'min_in', @max_in AS 'max_in', @min AS 'min', @max AS 'max', @rand, @rand_num AS 'rand_num', @out AS 'out'

 -- return appropriate
 RETURN @out;

-------------------------------------------------------------------------------

END;
GO

So where do you get the code?

You can view all functions and view online at the following gist.github urls:

Or you can just download all the source code in one zip file here.

Hopefully this will help somebody out.  If you’re a DBA or just a tsql wizard, let me know what you think.  Can I do these functions a better way?  Is this already built into SQL2005 and I just didn’t know it?  All of this tsql was written against SQL Server 2005, but I’m pretty sure it would work on SQL2000 and SQL2008 as well.

I built a calendar in a tSQL SPROC

Here’s a blast from the past that I recently found in my archives. It’s a novelty stored procedure I wrote during my MS SQL 2000 DBA days.
Back when I wrote this sproc, I was really big into writing calendar applications. I have written some sort of calendar application in
almost every language I know, so writing one in tSql made sense to me.

While I never used this sproc in an application, or had any practical use for it, I still think it’s cool. It’s primarily an excercise using
tSql’s date functions, and my all time favorite feature of MS SQL 2000+, table variables.

If you use MSSQL 2000 or higher and don’t use table variables, I highly recommend looking into these. In a nutshell, it’s a type of tSql variable
that is a table. You can select, insert, update, and delete the rows in this variable just like it’s a real table. The lifespan of a table variable
is the length of your connection to your db. So if you have a table var #myTable in sprocA, as soon as sprocA completes execution, #myTable is gone.
SprocB can’t access #myTable unless is specifically creates a new table var by this name.

So I wrote an article about this sproc for a database site years ago and I haven’t been able to find it again. This was web1.0 days, so I’m sure the site
is gone by now. The good thing is I still have the sproc, and now you can to.

So here’s the info. The sproc efCalendar accepts a month number and year number, and spits out two recordsets.

  1. Month, Year
  2. Calendar view of that month

Recordset 1 is two columns, month name, and year.

Recordset 2 is a calendar view of the specified month. There is a column for each weekday, starting with Sunday and ending with Saturday.
Then there is a row for each week in the specified month.

Here is what the results look like when run in Query Analyzer.

tSQL calendar sproc

tSQL calendar sproc

Download the efCalendar sproc here.

Create comma seperated list out of a sql query ( tsql )

Surfing the net for a sql answer, I came across something really cool. Below is an example of how to create a comma separated list of values in a single query.

–declare holder var
DECLARE @list VARCHAR(8000)

–build comma separated list
SELECT @list = COALESCE(@list + ‘, ‘, ”) + CAST(track_id AS VARCHAR(5) )
FROM webtool_tracks

–show results
SELECT @list AS ‘list’

The results should look something like this