Posts tagged: SQL

Enterprise Library Sometimes Chops XML into 2033 Characters

This morning I began what I thought would be an uneventful task in .NET: connect to one database, download as XML some rows from a table that have changed since a given time, then pass that XML to a stored procedure in another database so that the changes can be merged. Just two tables: one relatively small, the other just a 2-column relationship table for the first table. Here’s a contrived snippet to serve the same purpose:

The SQL:

CREATE PROCEDURE dbo.GetXmlValue

AS

SELECT TOP 100
 *
 FROM sys.all_columns
 FOR XML AUTO, ROOT('Root')

The Code:

Database db = GetDatabase();

DataSet set;

using (DbCommand cmd = db.GetStoredProcCommand("dbo.GetXmlValue"))
 {
     set = db.ExecuteDataSet(cmd);
 }

In my application, it was this second table that tripped me a bit. The first only had a few changed rows, so the XML was only 500-1000 characters. The second table generated a much longer XML string – 3864 characters long. My initial plan was to return two tables, each 1 column and 1 row. When using Database.ExecuteDataSet to fetch the results, however, the second table yielded two rows. I backtracked, second guessed myself, and even grabbed a couple of guys in the hall to double check my code. No one could explain it. It seemed odd that this hasn’t come up before for someone here. I did a bit of Googling and only found a couple of results. This Microsoft Knowledgebase Article just says it’s “by design” and to use SQLCommand.ExecuteXmlReader.

The next question that came up was “Well, what does it do if I return a long XML value among other values in the same row?” I tested this out and everything worked as expected. All of the XML was in a single column value as it should be.

I still can’t exactly explain it. ExecuteScalar has a character limit of 2033 characters. I suspect that because each table in my result set is just a single column value, something somewhere is relying on ExecuteScalar.

My solution? In my stored procedure I just stored each of my table results as an XML typed variable, then returned the two together in the same row.

GTIN 12 UPC Check Digit Calculation in SQL Server 2008

I recently needed to generate the check digit for a GTIN-12 UPC code in SQL. The calculation method for the check digit varies depending on what kind of barcode you’re implementing, so I popped on over to Google to get the necessary algorithm. Naturally, and regardless of simplicity, I checked for any available code snippets. The only I found weren’t GTIN-12, and were in C or C++. So for anyone looking to do it (or something similar) in T-SQL, here’s a scalar function to do just that.

CREATE FUNCTION dbo.CalculateBarcodeGTIN12CheckDigit(@input CHAR(11))
RETURNS INT
AS
BEGIN
	DECLARE @evenDigitSum INT = 0
		,@oddDigitSum INT = 0
		,@i TINYINT = 0
		,@result INT;

	-- check if given Barcode is Numeric , if not return error status -1
	IF(ISNUMERIC(@input) = 0
		OR LEN(RTRIM(LTRIM(@input))) != 11)
		RETURN -1

	-- start the compute BarCode checksum algorithm
	SET @i = 1
	WHILE (@i <= 11)
		BEGIN
		 --Add odd and even digits separately;
		 IF((@i % 2) = 0)
			 SET @evenDigitSum += CONVERT(TINYINT, SUBSTRING(@input,@i,1))
		 ELSE
			 SET @oddDigitSum += CONVERT(TINYINT, SUBSTRING(@input,@i,1))
		 SET @i += 1
		END

	--As per: http://en.wikipedia.org/wiki/Universal_Product_Code
	--Multiply odd sum by 3, add to even sum, and mod 10.
	SET @result = ((@oddDigitSum * 3) + @evenDigitSum) % 10;
	IF(@result = 0)
		RETURN 0
	ELSE
		RETURN 10 - @result;

	RETURN -1
END
GO

Scalar functions are killer, but I’ll only ever be using it for a single record.

SSMS Tools Pack Makes My Life Easier

I don’t currently do a lot of whiz-bang magic in my current job role. The majority of my day consists of writing reports, which can be boiled down to any of the follow:

  • Writing a stored procedure to generate the report data
  • Creating the report layout in a WYSIWYG-style editor.
  • Writing SQL script to deploy those changes to our customers.

The most exciting part is generally when I need to roll up my sleeves and figure out something fancy for the stored procedure. Much more often though, I’m hammering out INSERT scripts or UPDATE scripts with some XML stored as VARCHAR(MAX).

Because of the robotic nature of some of this, I decided to start using some code snippets. I couldn’t find any snippet feature in SQL Sever Management Studio, so I discovered SSMS Tools Pack.

image

This add-on has already saved me an enormous amount of time. I’ve only used a few of the features so far. SQL code snippets have obviously saved me a lot of time, but I found some other uses that I didn’t expect. I often need to test a report across multiple databases. With the tool pack, I can right click on a script, click “Run on multiple targets” and be prompted with a list of text boxes for each database I want to run it against. There’s nothing particularly magical about this process – it just creates a new tab and separates copies of the script with ‘USE [DatabaseName]’ lines, but it saves me a reasonable amount of time.

If you spend much time in SSMS, I recommend giving it a whirl. The full list of features:

  • Run one script on multiple databases
  • Copy execution plan bitmaps to clipboard or file
  • Search results in Grid Mode or Execution Plans
  • Generate Insert statements from resultsets, tables, or database
  • Regions and Debug sections
  • Running custom scripts from Object Explorer
  • CRUD stored procedure generation
  • New query template

SSMS Tools Pack