SQL select mit aufwendigerer berechnung

###Zaunpfahl###

Lt. Commander
Registriert
Jan. 2010
Beiträge
1.600
Hallo
ich bräucht mal hilfe in SQL
arbeite mom mit MS SQL 2012, sollte aber auch auf 2008 laufen

So was hab ich denn überhaupt vor.
Quelle ist eine Tabelle mit einer ID.
Die id ist ein varchar (mit slashes...wie ich aber den brauchbaren teil bekommen habe ich schon..) und soll in eine andere tabelle umgewandelt in decimal system und als int eingfügt werden.
Wie das geht hab ich schon.
Blos das ganze funktioniert mit nur einem "hexstring".
Es sollen aber alle ids der quell tabelle umgerechnet und in die neue tabelle eingetragen werden.

Jemand ne idee wie man das am besten macht?


Hierzu hätt ich dann auch noch eine weitere Frage!
Ist es denn irgendwie möglich code zu verlinken??
Bzw. aufzurufen.. so wie Methoden? Dann könnte man das ganze auch ein wenig schöner und überslichtlicher gestalten können...

Code:
-- Ein Hexadezimalstring ohne 0x als Präfix
declare @hexstring varchar(30)
-- Ist der aktuelle Char, also stelle im atkuellen durchlauf
declare @hexchar varchar(5)
declare @sum bigint
declare @i bigint
declare @n bigint
set @i = 0
set @n = 0
set @sum = 0
set @hexstring = '1234'
 
  
    while @i<LEN(@hexstring)
    begin
       
   
                               set @hexchar = LEFT(RIGHT(@hexstring, @i+1), 1)
   
    
                               set @n =
                                               CASE @hexchar
                                                               WHEN '0' THEN 0
                                                               WHEN '1' THEN 1
                                                               WHEN '2' THEN 2
                                                               WHEN '3' THEN 3
                                                               WHEN '4' THEN 4
                                                               WHEN '5' THEN 5
                                                               WHEN '6' THEN 6
                                                               WHEN '7' THEN 7
                                                               WHEN '8' THEN 8
                                                               WHEN '9' THEN 9
                                                               WHEN 'A' THEN 10
                                                               WHEN 'B' THEN 11
                                                               WHEN 'C' THEN 12
                                                               WHEN 'D' THEN 13
                                                               WHEN 'E' THEN 14
                                                               WHEN 'F' THEN 15                

                                         
                                               END
   
    set @sum=@sum+@n*POWER(16, @i)
    set @i=@i+1
END
   
select @sum as sum, @i as i, @n as n, LEN(@hexstring) as hexstring, @hexchar as hexchar
 
Soweit ich weiß, kannst du mit der convert-funktion auch direkt hex-werte in einen int casten.

Generell kannst du deinen code immer (wie in deinem Beispiel) in eine Funktion bzw. Prozedur kapseln. Hier wäre eine skalarwert-funktion sinnvoll.
Allerdings glaube ich, dass in diesem Fall concert() ausreichen sollte.
 
also ich habs mit convert und cast nicht hinbekommen von hex der aber ein string ist in dezimal und int umzuwandeln..
beispiel? :)

aber irgendwas innerhalb der prozedur gibts nich mehr?
du meinst also einmal für den insert ne prozedur und dann nochmals für die hexstring to decimal int eine prozedur
 
egal was man versucht man erhält immer diesen Fehler

Fehler beim Konvertieren des varchar-Werts '0x41' in den int-Datentyp.

und ein datentyp für hexwerte hab ich bis jetz nich gefunden..
Ergänzung ()

aber eigentlich war die frage eine andere

ich möchte ja einen string der eigentlich eine hexadezimal zahl ist in einen int umwandeln und dann in eine andere tabelle 'inserten'
aber halt nich einen wert sondern eine ganze spalte mit x zeilen mit x hexadezimalzahlstrings
Ergänzung ()

oder nochmals anders
was auch eine sehr brauchbare lösung wäre

das ich die Funktion irgendwie einbauen kann??

weil den select insert hab ich eigentlich schon
hier nimmt er ja auch immer jeden wert einzeln und schreibt in dann rüber
unterschied wäre nur das er einen wert nimmt umwandelt und dann erst rüberschreibt.

der select insert sieht wie folgt aus:

Code:
INSERT INTO tbl_ziel (ID)
    SELECT IDold
    FROM tbl_quelle 
    WHERE  IDold = (SELECT IDold
            FROM tbl_quelle LEFT JOIN tbl_ziel ON ID = IDold
            WHERE ID is NULL AND tbl_quelle.IDold = IDold)
 
Zuletzt bearbeitet:
Dann schreibe dir einfach ne skalarwert-funktion, der du einen string übergibst und einen int zurücklieferst. Den code dafür hast du ja eigentlich schon.

Wenn der code mit convert() fehlschlägt, könnte man alternativ eine clr-funktion schreiben. Die Konvertierung wäre mit .net relativ einfach zu realisieren. Dies aber nur als Anmerkung, führt evtl. etwas zu weit.

Edit: Dein select into ist auf jeden Fall der richtige Ansatz, um Daten aus einem resultset in eine Tabelle zu speichern.
 
Zuletzt bearbeitet:
Danke für die Antwort
genau das hab ich jetz vorhin schon gemacht^^

lösung sieht wie folgt aus

1. Erstelle Skalarwertfunktion
Code:
CREATE FUNCTION [dbo].[hexstr_to_int] 
(
	@hexstring varchar(30)
)
RETURNS int
AS
BEGIN
	-- Ein Hexadezimalstring ohne 0x als Präfix
--declare @hexstring varchar(30)
-- Ist der aktuelle Char, also stelle im atkuellen durchlauf
declare @hexchar varchar(5)
declare @sum bigint
declare @i bigint
declare @n bigint
set @i = 0
set @n = 0
set @sum = 0
--set @hexstring = '1234'
 
  
    while @i<LEN(@hexstring)
    begin
       
   
                               set @hexchar = LEFT(RIGHT(@hexstring, @i+1), 1)
   
    
                               set @n =
                                               CASE @hexchar
                                                               WHEN '0' THEN 0
                                                               WHEN '1' THEN 1
                                                               WHEN '2' THEN 2
                                                               WHEN '3' THEN 3
                                                               WHEN '4' THEN 4
                                                               WHEN '5' THEN 5
                                                               WHEN '6' THEN 6
                                                               WHEN '7' THEN 7
                                                               WHEN '8' THEN 8
                                                               WHEN '9' THEN 9
                                                               WHEN 'A' THEN 10
                                                               WHEN 'B' THEN 11
                                                               WHEN 'C' THEN 12
                                                               WHEN 'D' THEN 13
                                                               WHEN 'E' THEN 14
                                                               WHEN 'F' THEN 15                

                                         
                                               END
   
    set @sum=@sum+@n*POWER(16, @i)
    set @i=@i+1
END
return @sum;

END

GO


Funktion verwenden:
Code:
    INSERT INTO tbl_ziel (ID)
    SELECT dbo.hexstr_to_int(IDold)
    FROM tbl_quelle
    WHERE IDold = (SELECT IDold
    FROM tbl_quelle LEFT JOIN tbl_ziel ON ID = IDold
    WHERE ID is NULL AND tbl_quelle.IDold = IDold)


Funktioniert super
Danke für die Hilfe, wenn ich jetz nich vor dir selbst das enstsprechende Werkzeug gefunden hätte, hättest mich sofort dahin gelotzt^^



[für google]
<< Hexadezimal als Datentyp varchar in Dezimalzahl Datentyp int umwandeln >>
 
Zuletzt bearbeitet:
Ich habe nochmal kurz nachgeforscht:
Das Problem bei dir ist, dass der Hex-Wert als String-Datentyp vorliegt.
Du musst also den string zuersteinmal in einen varbinary konvertieren.
Aber auch hier schlägt der Standard-Convert fehl (bzw. das Ergebnis ist nicht das, was man erwartet), weil er die String-Bytes als ASCII-Zeichen interpretiert.

Seit SQL Server 2008 geht dies aber auch über die convert-Funktion via 'style':
http://msdn.microsoft.com/de-de/library/ms187928.aspx (siehe Abschnitt "Binäre Formate")

Somit klappt es auch mit der integrierten Funktion von MS und du kannst dir eigentlich die eigene sparen:
Code:
select convert(int, convert(varbinary, '0x00000A', 1))
 
Zuletzt bearbeitet:
hast recht, hab ich doch glatt übersehen
aber ist auch ein wenig unübersichtlich...bis jetz hab ich das nur im zusammenhang mit ascii zeichen gesehen...


in meinem fall wäre dann aber methode 2 also ohne 0x davor eher relevant

hinzu kommt das immer 6 zeichen erwartet werden, ok in meinem fall wärs momentan konstant, aber wenn sich das doch mal ändert (kann selbst nicht beeinflusst werden)
das kann mein code besser, der wandelt den ganzen varchar in int um egal wie lang..

und der integrierte geht bis maximal 0xFFFFFF (16.777.215) meiner kann bis 0x7FFFFFFF (2.147.483.647) dann gibts nen arithmetischen überlauf

aber trotzdem danke für deine bemühung :)
 
Die integrierte Funktion kann genauso auch länger als 6-stellige HexWerte entgegennehmen.
Du musst natürlich beim casten dementsprechend auf bigint umstellen, sonst knallts.

Voila:
Code:
DECLARE @myString nvarchar(50) = 'FFFFFFFFFFFF'
DECLARE @myStyle int

IF left(@myString, 2) <> '0x'
SET @myStyle = 2
ELSE
SET @myStyle = 1

SELECT convert(bigint, convert(varbinary, @myString, @myStyle))
 
Zuletzt bearbeitet:
Code:
declare @hexstring varchar(max);
set @hexstring = '0x7FFFFFFF';
select convert(int, convert(varbinary(max), @hexstring, 1))

Läuft bei mir auf 2012 obs auf 2008 auch läuft müsste man testen

Falls ohne 0x gewünscht ist müsste man halt beim convert ne 2 statt ne 1 setzen

/e zu langsam :(
 
also sobald man von den 6 zeichen abweicht kommt bei mir die meldung:

Fehler beim Konvertieren des varchar-Datentyps in varbinary.
da bringt bigint auch nix


ms sql svr 2008 R2 (x64)
Ergänzung ()

lol

wenn ich so wie thecain mach und erst eine variable deklarier, dann funktionierts
Ergänzung ()

OK jetz hab ich den "Fehler" gefunden.

der hexstring muss immer eine gerade Anzahl von Ziffern haben damit das funktioniert
Ergänzung ()

wie mach ich das dann in einem insert into?
also ich würd schon gern abfangen das der hexdezimalstring länger ungerade lang is

und dann hätt ich noch was
wie mach ich denn einen vergleich mit zwei Daten (Zeit)
also wie muss ich die angeben
is eigentlich ganz einfach..möcht eigentlich nur ein festes datum ist größer als datum aus spalte
Code:
column_date > 01.01.1990
wobei mir fällt grad ein fehler auf........
 
Zuletzt bearbeitet:
Prüfen, ob der String gerade ist, kannst du mit dem %-Operator:

Code:
DECLARE @myString nvarchar(50) = 'FFFFFFFFFFFFF'
DECLARE @myStyle int

IF len(@myString) % 2 = 0
BEGIN

	IF left(@myString, 2) <> '0x'
	SET @myStyle = 2
	ELSE
	SET @myStyle = 1

	SELECT convert(bigint, convert(varbinary, @myString, @myStyle))
END
ELSE
BEGIN
	PRINT '@myString ungerade!!'
END

Zum Datum Thema:
Wenn du das Datum in der Reihenfolge Tag.Monat.Jahr angeben möchtest, solltest du dies vorher auch so festlegen, da je nach Servereinstellung hier Unterschiede auftreten:

Code:
SET DATEFORMAT dmy

DECLARE @dateString nvarchar(50) = '01.01.2014'

SELECT cast(@dateString as DATETIME)
 
zu 1.
ja nicht ganz^^

ich hab eigentlich gemeint ob es eine möglichkeit gibt das innherhalb der insert klausel zu machen, aber da kann man denk ich mal keine auswahl einbauen

hätte es dann nämlich so machen wollen, das er bei ungerade dem hexstring eine 0 vorne anhängt und bei gerade nicht..........oder man hängt einfach die anzahl der aktuellen länge des hexstrings von 0en vorne dran dann wärs auch imma gerade^^


2.
ah ok
schon wieda denkfehler
eigentich wollt ich wissen wie man ein datum schreiben muss damit es als Datum erkannt wird.
Ich schätz mal, dass das nich geht und man sich jedesmal ein datum casten muss
 
Zuletzt bearbeitet:
zu 1.:
Na klar sollte das gehen, mit CASE WHEN:
Code:
CASE WHEN len(@myString) % 2 = 0 THEN @myString ELSE '0' + @myString END

zu 2.:
Genau, einfach einen String in einen Datetime casten
 
Zurück
Oben