Monday, September 23, 2013

SQL - Calling Stored Procedure with Comma Separated List in Input Parameter

Background

Currently I am programming on an ASP.NET web application with a data connection to a MS SQL Server 2008 R2 database. I am fetching data always via stored procedures. Today I came across the problem that I wanted to program a procedure where I have to do a SELECT with a WHERE column IN (...) with an unknown number of arguments in the IN statement.
Hence I was looking for a way to transfer a comma separated list as string parameter into the WHERE IN argument.

First Try

The straight forward approach I tried looked like this:

CREATE PROCEDURE [dbo].[MyProcedure]
@inputList nvarchar(MAX) <- comma separated list of values (string)
AS
BEGIN
      SELECT * FROM myTable
      WHERE
      colName IN (@idList)
END
GO

Unfortunately, this approach does not work. You can inject a list with on list element which will return some reasonable result, but as soon as you call this with list with more than one argument, this fails, as the argument is not interpreted as WHERE IN ('arg1','arg2') but as WHERE IN ('arg1,arg2').

Solution

After some research I stumbled over a Code Project thread which was the key to solve the problem. To have a more ready-to-use description I wrote this blog. With the help of the above thread I wrote the following stored procedure:

CREATE PROCEDURE [dbo].[myWorkingProcedure]
@inputList nvarchar(MAX)
AS
DECLARE @SEPERATOR as VARCHAR(1)
DECLARE @SetPoint INT
DECLARE @VALUE nvarchar(50)
CREATE TABLE #tempTab (id nvarchar(50) not null)
BEGIN
SET NOCOUNT ON;
WHILE PATINDEX('%,%',@idList) > 0 <-- Drive loop while commata exist in the input string
BEGIN
SELECT  @SP = PATINDEX('%,%',@idList) <-- Determine position of next comma
SELECT  @VALUE = LEFT(@idList , @SP - 1) <-- copy everything from the left into buffer
SELECT  @idList = STUFF(@idList, 1, @SP, '') <-- throw away the stuff you copied
INSERT INTO #tempTab (id) VALUES (@VALUE) <-- put value in buffer table
END
INSERT INTO #tempTab (id) VALUES (@idList) <-- insert last value in the input list to buffer
BEGIN
SELECT * FROM myTable
WHERE
myColumn IN (SELECT id FROM #tempTab) <-- Do the select
DROP TABLE #tempTab <-- throw buffer table away
END
END
GO

Conclusion

With the help of the above code it is possible to perform dynamic SELECT WHERE IN statements with an unknown number of arguments. I hope this post helps you to overcome your own problems with transactional SQL


all the best
WolfiG

Sunday, September 1, 2013

Prinzessinnen-Bett im Selbstbau mit Bauplan

Liebe Leser,

unsere Töchter entwachsen langsam ihren Babybettchen / Gitterbettchen. Vor allem die Große ist inzwischen mit 3 1/2 Jahren und 104 cm so groß, dass sie in mittelfristiger Zeit ein neues Bett braucht. Sie träumt von einem Prinzessinnenbett, natürlich am liebsten als Hochbett. Die Kleine ist 20 Monate alt, insofern kommt für sie im Moment kein Hochbett in Frage.
Weiterhin möchten wir die beiden Kinder für die nächsten Jahre in einem gemeinsamen Schlafzimmer unterbringen. Wir können also momentan kein Hochbett für die Große anschaffen, da beide Kinder im gleichen Zimmer herumtollen werden. Was wir aber gerne hätten, wäre ein Bett, das "mitwächst", also das sich umbauen lässt. Da Bett sollte für unsere Große als Prinzessinnen-Bett ("normal") begonnen werden und dann so aufgebaut sein, dass es durch Module erweiterbar ist, idealerweise in ein paar Jahren zum Hochbett.
Weitere Anforderungen / Spezifikationen des zu bauenden Betts:

  • Standardmaß für Lattenrost und Matratze (90 x 200 cm)
  • Unter dem Bett sollten große Schubladen Platz haben um Bettwäsche dort unterzubringen
  • Kompatibilität mit den Maßen eines Bettes von einem beliebten Kinderbettherstellers (L x B: 201,4 x 97,9) um das Zubehör dazu nutzen zu können. Ich habe allerdings eine größere Höhe gewählt, als das Bett von P.... um mehr Platz für einen großen Bettkasten zu schaffen.
Für die Erstellung der technischen Zeichnungen verwende ich LibreCAD, CorelCAD 2014 und für die der 3D-Darstellungen Blender

Der "Standard"-Rahmen

Um ein Bettsystem modular aufzubauen, brauchen wir einen Rahmen, der einen "Standard" darstellt, und auf Basis dessen das Bettsystem aufgebaut wird. Wie oben beschrieben, möchte ich den Rahmen auf Standard-Lattenrost- und Matratzenmaßen aufbauen. Ich habe im Moment die folgenden, im Internet erhältlichen Produkte als Arbeitshypothese ausgewählt:
  • Lattenrost "Sirius" von Breckle, erhältlich bei Home24, eine Alternative ist ein Lattenrost von IKEA 
  • passende Matratze ebenfalls bei Home24

Bettgestell im Eigenbau

Als Ausgangsmaterial habe ich im Baumarkt erhältliche Vierkant-Hölzer aus Kiefer (54 x 54 mm) verwendet. Es hat sich allerdings aber beim Bau herausgestellt, dass ein anderes Holz besser gewesen wäre, ich denke, Buche vom Schreiner wäre besser gewesen. Hier die Materialliste:

  • 7 Vierkant-Hölzer 54 x 54 mm x 3 m
  • 2 Vierkanthölzer 20 x 20 mm x 2m
  • 3 Vierkanthölzer 10 x 10 mm x 2 m
  • 2 Spanplatten 90 x 45 x 8 mm
  • Holzleim
  • 4 x Möbelverbinder mit Schrauben der Länge 80 mm
  • Rundholz, Durchmesser 25 mm, Länge 1 m
  • Riffelstange, Durchmesser 12 mm, Länge 1 m

Das Material hat ungefähr 120.- € gekostet.
Weiterhin standen mit als Werkzeug folgendes zur Verfügung:

  • Stichsäge
  • Bohrmaschine
  • Bohrer der Durchmesser 6, 7, 12, 25 mm
  • Schraubzwingen
  • Exzenterschleifer
Zusammengebaut sieht mein Gestell so aus:



Das ganze nochmal als Explosionszeichnung:

Im Original sieht das ganze zusammengebaut so aus:


Verbindung der Einzelteile

Mein Ziel beim Bettbau war es, die Teile so wenig wie möglich zu verschrauben, und gleichzeitig eine größtmögliche Stabilität zu erreichen. Da ich keine Oberfräse zum anfertigen von Schwalbenschwänzen habe (und auch ein zu unruhiges Händchen um das mit der Säge zu machen), entschied ich mich dazu, die Rahmenhölzer mittels "geradem Eckblatt" zu verbinden. Die beiden Hölzer werden dabei verklebt und zusätzlich durch einen durchgebohrten 12 mm Holzdübel (aus Riffelholz) verbunden.
Die Rahmenteile sehen im Original so aus:

Um die Längsschenkel zu befestigen, wollte ich es vermeiden, die Teile zu verkleben, um das Bett gut wieder verlegen zu können. Dazu habe ich eine Verzapfung mittels 25 mm Rundhölzern gewählt. Um die den Lattenrost tragenden Schenkel zu befestigen, sichere ich die verzapften Teile noch mit Möbelverbindern, für die die Rundhölzer mit einem 6-7 mm Loch entlang der Zapfen-Längsachse versehen werden.

Mai 2014 Update: So Sieht's aus

So, jetzt ist mein Werk bis auf einen zweiten Anstrich fertig. Ich habe noch eine Baldachin-Konstruktion auf Kanthölzern 54x54mm dazugebaut, damit ein Baladachin von PAIDI über dem Bett angebracht werden kann. In diesem Stadium bin ich ganz zufrieden:

Einmal ohne Baldachin, um die Unterkonstruktion zu zeigen


Einmal mit Baldachin und Bettzeug