2009-08-04 4 views
1

Ich habe eine gespeicherte Prozedur in einer alten SQL 2000-Datenbank, die eine Kommentarspalte, die als Varchar formatiert ist, übernimmt und als Geldobjekt exportiert. Zu der Zeit, als diese Tabellenstruktur eingerichtet wurde, wurde angenommen, dass dies die einzigen Daten sein würden, die in dieses Feld gelangen. Die aktuellen Verfahren funktioniert einfach dies folgt aus:Wie tryParse in SQL 2000?

SELECT CAST(dbo.member_category_assign.coment AS money) 
    FROM dbo.member_category_assign 
WHERE member_id = @intMemberId 
     AND 
     dbo.member_category_assign.eff_date <= @dtmEndDate 
     AND 
     (
     dbo.member_category_assign.term_date >= @dtmBeginDate 
     OR 
     dbo.member_category_assign.term_date Is Null 
     ) 

jedoch werden Daten nun in dieser Spalte eingefügt wird, die nicht zu einem Geld Objekt geparst und verursacht das Verfahren zum Absturz bringen. Ich bin nicht in der Lage, die "schlechten" Daten zu entfernen (da dies ein Produkt eines Drittanbieters ist), muss aber die gespeicherte Prozedur aktualisieren, um einen Geld-Parsable-Eintrag zu testen und diesen zurückzugeben.

Wie kann ich diese Prozedur aktualisieren, sodass nur der Wert zurückgegeben wird, der als Geldobjekt analysiert werden kann? Erstelle ich eine temporäre Tabelle und durchlaufe jedes Element, oder gibt es dafür einen clevereren Weg? Ich stehe mit Legacy SQL 2000 (Version 6.0) fest, daher ist die Verwendung einer der neueren Funktionen leider nicht verfügbar.

Antwort

7

Die Überprüfung auf IsNumeric kann Ihnen helfen - Sie können einfach einen Nullwert zurückgeben. Wenn Sie eine 'N/a' oder einen anderen Zeichenfolgenwert zurückgeben möchten, habe ich das folgende Beispiel mit den Spalten aus Ihrer Abfrage erstellt

.

Die erste Abfrage gibt nur alle Zeilen zurück.

Die zweite Abfrage gibt einen GELD-Wert zurück.

Der dritte gibt einen String-Wert mit N/A anstelle des nicht ganzzahligen Werts zurück.

set nocount on 
drop table #MoneyTest 
create table #MoneyTest 
(
    MoneyTestId Int Identity (1, 1), 
    coment varchar (100), 
    member_id int, 
    eff_date datetime, 
    term_date datetime 
) 
insert into #MoneyTest (coment, member_id, eff_date, term_date) 
values 
    (104, 1, '1/1/2008', '1/1/2009'), 
    (200, 1, '1/1/2008', '1/1/2009'), 
    (322, 1, '1/1/2008', '1/1/2009'), 
    (120, 1, '1/1/2008', '1/1/2009') 

insert into #MoneyTest (coment, member_id, eff_date, term_date) 
values ('XX', 1, '1/1/2008', '1/1/2009') 

Select * 
FROM #MoneyTest 

declare @intMemberId int = 1 
declare @dtmBeginDate DateTime = '1/1/2008' 
declare @dtmEndDate DateTime = '1/1/2009' 

SELECT 
    CASE WHEN ISNUMERIC (Coment)=1 THEN CAST(#MoneyTest.coment AS money) ELSE cast (0 as money) END MoneyValue 
FROM #MoneyTest 
WHERE member_id = @intMemberId 
AND #MoneyTest.eff_date <= @dtmEndDate 
AND 
(
    #MoneyTest.term_date >= @dtmBeginDate 
    OR 
    #MoneyTest.term_date Is Null 
) 

SELECT 
    CASE WHEN ISNUMERIC (Coment)=1 THEN CAST (CAST(#MoneyTest.coment AS money) AS VARCHAR) ELSE 'N/a' END StringValue 
FROM #MoneyTest 
WHERE member_id = @intMemberId 
AND #MoneyTest.eff_date <= @dtmEndDate 
AND 
(
    #MoneyTest.term_date >= @dtmBeginDate 
    OR 
    #MoneyTest.term_date Is Null 
) 
+0

Schön! Lief wie am Schnürchen! Vielen Dank! –

2

Apologies für eine neue Antwort zu machen, wo ein Kommentar würde genügen, aber mir fehlt die erforderlichen Berechtigungen, dies zu tun. Auf die Antwort auf Ihre Frage möchte ich nur hinzufügen, dass Sie die obige ISNUMERIC sorgfältig verwenden sollten. Während es wie erwartet funktioniert, analysiert es auch Dinge wie '1.3E-2' als Wert numerisch, was merkwürdigerweise nicht in Zahlen oder Geld umgewandelt werden kann, ohne eine Ausnahme zu erzeugen. Ich benutze im Allgemeinen am Ende:

SELECT 
    CASE WHEN ISNUMERIC(some_value) = 1 AND CHARINDEX('E', Upper(some_value)) = 0 
     THEN Cast(some_value as money) 
     ELSE Cast(0 as money) 
    END as money_value