none
Wechsel von SQL2000 zu SQL2008 RRS feed

  • Frage

  • Hallo zusammen,

    wir betreiben seit vielen Jahren eine Website mit ASP und SQL2000. Alles funktioniert soweit einwandfrei, allerdings ist die Geschwindigkeit, bedingt durch immer weiter steigende Datenvolumen, nicht mehr optimal.

    Also soll jetzt der Umstieg auf SQL2008 vorgenommen werden.

    Wenn ich also die ASP-Seiten gegen eine Kopie der Datenbank auf einem SQL2008-Datenbankserver verlinke, funktoniert ein Teil der Seiten scheinbar problemlos, bei anderen scheint es Anpassungsbedarf zu geben.

    Konkret scheint ein Problem in folgender Kombination zu liegen:

       

    DIM lanr, rslnr, cmd, dDate
      Set cmd = Server.CreateObject("ADODB.Command")
      Set rs = Server.CreateObject("ADODB.Recordset")
      cmd.ActiveConnection = con


    Folgender Part scheint soweit normal zu funktionieren:

       

     cmd.CommandText = "sp_Get_lieferanschriftnummer_by_example '" & _
        qstr(strname1) & "', '" & qstr(strname2) & "', '" & qstr(strname3) & "', '" & qstr(strstrasse) & "', '" & _
        qstr(strplz) & "', '" & qstr(strort) & "', '" & qstr(strBemerkung) & "', '" & _
        qstr(strEtage) & "', '" & qstr(strAbteilung) & "', " & strKundenNrAktuell & ", '" & strKuerzel & "', '" & session("PartnerOrt") & "'"
           rs.Open cmd
           if not rs.EOF then
           rslnr = rs.Fields(0)
           else
           rslnr = 0
           end if
           rs.Close
        cmd.CommandText = "sp_INS_Bestellung_Values3 " & _
        strKundenNrAktuell & ", '" & qstr(StrBenutzer) & "', '" & qstr(strBestelltext) & "', '" & _
        qstr(strkostenstelle) & "', '" & strkostentraeger & "', '" & strProjekt & "', '" & _
        qstr(strStatus) & "', '" & strKuerzel & "', '" & _
        qstr(strname1) & "', '" & qstr(strname2) & "', '" & qstr(strname3) & "', '" & qstr(strstrasse) & "', '" & _
        qstr(strplz) & "', '" & qstr(strort) & "', '" & qstr(strBemerkung) & "', '" & _
        qstr(strEtage) & "', '" & qstr(strAbteilung) & "', '" & session("PartnerOrt") & "', " & rslnr & " , '" & date() & "'"
        Response.Write "<p>" & cmd.CommandText & "</p>"
        cmd.Execute

    Und ab hier vermute ich das Problem:

        'Response.Write(cmd.CommandText)
        cmd.CommandText = "spWebGetNeueBestellNummer"
        rs.Open cmd
        DIM strNeuBestellNr
        if not rs.EOF then
          strNeuBestellNr = rs.Fields(0)
        end if
        rs.Close
        session("Bestellnr") = strNeuBestellNr

    In strNeuBestellNr scheint nix anzukommen, somit kommt auch in session("Bestellnr") kein Wert an und das führt dann dazu, daß später folgende Programme auf Grund der fehlenden BestellNr nicht mehr richtig verarbeiten werden können.

    Der Fehler scheint unabhängig davon zu sein, ob die Datenbankkopie als kompatibel zu SQL2000 oder kompatibel zu SQL2008 ausgeführt wird.

    Die ASP-Seiten sind eigentlich unverändert, lediglich der Connection-String wurde auf das veränderte Backend angepaßt:

    strConnString  = "Provider=SQLOLEDB.1;Password=xxxxx;Persist Security Info=True;User ID=yyyyy;Initial Catalog=BSM WWW Kopie;Data Source=DEV03"


    als auch


     

    strConnString  = "Provider=SQLNCLI10;Password=xxxxx;Persist Security Info=True;User ID=yyyyy;Initial Catalog=BSM WWW Kopie;Data Source=DEV03"



    Das Problem tritt auf, egal mit welchem Connection-String die Verbindung zur Datenbank hergestellt wird.

    Die StoredProc spWebGetNeueBestellNummer:

    SET
    ANSI_NULLS OFF
    GO
    SET QUOTED_IDENTIFIER OFF
    GO CREATE PROCEDURE [dbo].[spWebGetNeueBestellNummer] 
    AS
    SELECT IDENT_CURRENT( 'www input Bestell-Header') as [KD-Bestell-Nr]
    Donnerstag, 27. Mai 2010 15:39

Antworten

  • Hallo Peter,

    für Ident_Current reicht es völlig aus, wenn man zumindest SELECT Rechte auf der Tabelle; Vermerk dazu habe ich in der Doku nicht gefunden, aber es ausprobiert und ist ja auch (fast) logisch; man muss zumindest Daten aus der Tabelle lesen dürfen, um auch den letzten Wert erfahren zu dürfen. Mit Scope_Identity ist es genaus so. "Nur" INSERT Rechte gehen ebenso.

    Mit MAX() zu arbeiten, wird igendwann mal daneben gehen, Elmar hatte es ja auch schon gesagt. Eine weitere Option wäre, mit der OUTPUT Klause des INSERT Befehles zu arbeiten, um die ID(s) zu ermitteln.

     


    Olaf Helper ----------- * cogito ergo sum * errare humanum est * quote erat demonstrandum * Wenn ich denke, ist das ein Fehler und das beweise ich täglich http://olafhelper.over-blog.de
    Dienstag, 15. Juni 2010 11:12
  • Hallo zusammen,

    so wie es aussieht, waren wir wohl alle gemeinsam auf 'nem falschen Dampfer unterwegs.

    Also, ich habe nun versucht, meine behelfsmäßig geänderte StoredProc mit select max(BestellNr) from tabelle wieder in ein select ident_current('Tabelle') zu ändern, um dann weiter in Richtung Scope_Identity zu gehen.

    Im SQLSMS funktionierte die Befehlskette korrekt; auf der Webseite jedoch nicht. Der einzige Unterschied ist der verwendete User; als ich auf der Webseite den Verbindungs-User probeweise auf SA geändert habe, funktionierte sie auf Anhieb.

    Also, der User, der die Webseite mit der Datenbank verbindet, ist ein in den Rechten dramatisch gestutzter User (aus Sicherheitsaspekten). Welches Recht muß ich denn nun diesem User zusätzlich einräumen, daß er Ident_Current oder besser noch Scope_Identity verwenden kann ? Ein Betreiben der Webseite mit SA als Verbindungsuser kommt nicht in Frage.

    Viele Grüße

    Peter

    • Als Antwort markiert PHundhausen Dienstag, 27. Juli 2010 12:35
    Dienstag, 15. Juni 2010 10:25

Alle Antworten

  • Hi,

            qstr(strname1)  & "', '" & qstr(strname2)  & "', '" & qstr(strname3)  & "', '" & qstr(strstrasse)  & "', '" & _
            qstr(strplz)  & "', '" & qstr(strort)  & "', '" & qstr(strBemerkung)  & "', '" & _
            qstr(strEtage)  & "', '" & qstr(strAbteilung)  & "', '" & session("PartnerOrt") & "', " & rslnr & " , '" & date() & "'"

    Und ab hier vermute ich das Problem:

            'Response.Write(cmd.CommandText)
            cmd.CommandText = "spWebGetNeueBestellNummer"
            rs.Open cmd
            DIM strNeuBestellNr
            if not rs.EOF then
                strNeuBestellNr = rs.Fields(0)
            end if
            rs.Close
            session("Bestellnr") = strNeuBestellNr

    In strNeuBestellNr scheint nix anzukommen, somit kommt auch in session("Bestellnr") kein Wert an und das führt dann dazu, daß später folgende Programme auf Grund der fehlenden BestellNr nicht mehr richtig verarbeiten werden können.

    probier mal folgendes (vor rs.Open cmd):

    rs.CursorLocation = 3 'adUseClient

    Wenns nicht hilft, überwache die Ausführung mal mit dem SQL Server Profiler. Wenn es dasselbe ist wie bei mir damals, solltest Du sehen, dass intern jedesmal neue Verbindungen geöffnet werden.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Donnerstag, 27. Mai 2010 15:58
    Moderator
  • Hallo,

    Zunächst verwende CommandType=adCmdStoredProc .
    Im übrigen kann ich Dir nur empfehlen für alles Command-Objekte
    zusammen mit Parametern zu verwenden.
    Denn schon die Verketterei dürfte ihren Teil zu der Verlangsamung beitragen.

    Für die Prozedur verwende besser einen Ausgabe-Parameter und SCOPE_IDENTITY().
    Sich auf IDENT_CURRENT verlassen ist an der Stelle mehr als gewagt,
    ich verweise hier auf Managing an @@IDENTITY Crisis (die bei ADODB nicht anders ist)

    Eine bessere Lösung könnte angedeutet wie folgt aussehen:

    SET QUOTED_IDENTIFIER ON
    GO
    CREATE PROCEDURE [dbo].[sp_INS_Bestellung_Values3]
    	@BestellNr int OUT,
    	-- Einzufügende Werte...
    	@Benutzer nvarchar(40) 
    	-...
    AS
    	SET NOCOUNT ON;
    	INSERT INTO dbo.Bestellung VALUES(@Benutzer, ....);
    	IF @@ROWCOUNT = 1
    	BEGIN
    		SET @BestellNr = SCOPE_IDENTITY();
    		RETURN 0; -- OK
    	END
    	RETURN 1;	-- Fehler
    GO
    

     

    Wenn Du nun den @BestellNr Parameter als adParamOutput erstellst,
    so kannst Du direkt darauf zugreifen, ohne Umweg über den ebenfalls langsamen Cursor.
    Und mit einem adParamReturnValue kannst Du auch die Rückgabe auswerten.
    Siehe auch How To Retrieve Values in SQL Server Stored Procedures with ADO

    Alles zusammen könnte die Performance verbessern - denn auch ein Wechsel
    auf SQL Server 2008 alleine wird bei CRUD Dingen nicht viel an Performance rausholen.

    Gruß Elmar

    Donnerstag, 27. Mai 2010 16:38
    Beantworter
  • Habe gesehen, daß Ihr mir schon Lösungsvorschläge aufgezeigt habt.

    Ich werde in den nächsten Tagen umgehend versuchen, die aufgeführten Vorschläge umzusetzen. Über die Ergebnisse werde ich dann umgehend berichten.

    Zu den einzelnen Rand-Kommentaren muß ich folgende Erklärungen machen:

    Die Site wurde ca 2001 / 2002 erstellt und seitdem täglich von vielen Usern genutzt. Als ich heute den IDENT_CURRENT gefunden habe, hatte auch ich ein mulmiges Gefühl. Aber in all den Jahren ist diesbzgl. niemals ein Fehler aufgetreten.

    Die Geschwindigkeitsprobleme treten nicht in dem hier gezeigten Problembereich auf. Allein durch den Wechsel auf SQL2008 konnte ich die Laufzeit einer Abfrage von 19 Sekunden auf unter 1 Sekunden verbessern, ohne daß irgendeine Optimierung erfolgt wäre.

    Gruß Peter

    Donnerstag, 27. Mai 2010 19:33
  • Hallo Peter,

    ich wollte damit nichts kritisieren und keiner kennt den SQL Server von Anfang an auswendig,
    ich lerne auch nach gut 12 Jahren dazu ;-)

    Zu IDENT_CURRENT gilt, das was (knapp) dokumentiert ist:
    "IDENT_CURRENT ist nur bedingt geeignet, um den nächsten generierten Identitätswert vorherzusagen.
    Der tatsächlich generierte Wert kann sich aufgrund von Einfügungen durch andere Sitzungen
    von IDENT_CURRENT plus IDENTITY_INCR unterscheiden."

    Problem ist das Identitätswerte nicht an Transaktionen teilnehmen.
    Und zwischenzeitlich eine andere Sitzung den Wert verändern kann.

    Zur Performance: Unter den vielen Faktoren, die die die Abfragegeschwindigkeit
    negativ beeinflußen können, gehören Blockierungen jeder Art an erste Stelle.
    Und Dein Einfüge Code ist der Form problematischer als der von mir gezeigte,
    wie ich am eigenen Leibe (als ich noch ADO verwendete) erfahren konnte.

    Gruß Elmar

    Donnerstag, 27. Mai 2010 19:55
    Beantworter
  • probier mal folgendes (vor rs.Open cmd):

    rs.CursorLocation = 3 'adUseClient

    Wenns nicht hilft, überwache die Ausführung mal mit dem SQL Server Profiler. Wenn es dasselbe ist wie bei mir damals, solltest Du sehen, dass intern jedesmal neue Verbindungen geöffnet werden.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Hallo Stefan,

    Hab ich schon ausprobiert; hat leider keinen Erfolg gebracht

    Hab auch mit dem SQL-Profiler überwacht; intern wurde aber für den gesamten Anweisungsblock nur 1 Verbindung genutzt

    Werde dann wohl als nächtes Mal den Vorschlag von Elmar durcharbeiten.

    Vielen Dank für Deine Hilfe

    Peter

    Freitag, 28. Mai 2010 09:32
  • Hallo Peter,

    ich habe mal einen Codeschnippsel rausgesucht.
    Der stammt zwar aus einer Access ADP/VBA (älteren Datums),
    sollte aber den vorgeschlagenen Aufbau relativ gut zeigen:

    Public Function Inventur_BelegFetch( _
      ByVal InventurNr As Long, _
      ByRef BelegNr As Long, _
      ByRef BelegPosNr As Integer) As Boolean
    ' Abruf einer neuen Belegnummer
      Dim cmd As ADODB.Command
      
      On Error GoTo ProcErr
      Set cmd = New ADODB.Command
      With cmd
        .CommandType = adCmdStoredProc
        .CommandText = "dbo.iv_InventurBelegFetch"
        .CommandTimeout = 5
        .NamedParameters = True
    
        .Parameters.Append .CreateParameter("@RETURN_VALUE", adInteger, adParamReturnValue)
        .Parameters.Append .CreateParameter("@InventurNr", adInteger, adParamInput)
        .Parameters.Append .CreateParameter("@BelegNr", adInteger, adParamInputOutput)
        .Parameters.Append .CreateParameter("@BelegPosNr", adSmallInt, adParamInputOutput)
    
        Set .ActiveConnection = GetDefaultConnection()
        
        .Parameters("@InventurNr").Value = InventurNr
        .Parameters("@BelegNr").Value = BelegNr
        .Parameters("@BelegPosNr").Value = BelegPosNr
        
        .Execute Options:=adExecuteNoRecords
        
        BelegNr = .Parameters("@BelegNr").Value
        BelegPosNr = .Parameters("@BelegPosNr").Value
      End With
    
      Inventur_BelegFetch = True
    ProcExit:
      Set cmd.ActiveConnection = Nothing
      Set cmd = Nothing
      Exit Function
    ProcErr:
      LogADOErrors "BelegFetch", , cmd.ActiveConnection
      FormError "Beleg Nummer"
      Resume ProcExit
    End Function
    Gruß Elmar

    Freitag, 28. Mai 2010 11:25
    Beantworter
  • Ich habe jetzt mal versucht, mich den Lösungsvorschlägen von Elmar anzunähern. Aber so richtig komme ich dabei noch nicht vorwärts.

    Als erstes hab ich Probleme, eine Procedur mit einem Output-Parameter zu erstellen. Zum Testen hab ich mal folgende StoredProc erstellt:

    --------------------
    create
    PROCEDURE [dbo].[spWebGetNeueBestellNummer] @BestellNr int Out
    AS
    set @BestellNr = 12345
    -------------------

    Zunächst versuche ich die wie folgt auszulesen:

    Declare @SQLCommand nvarchar(100), @SQLParameter nvarchar(100)
    Declare @Rueckgabewert int
    Declare @BestellNr int
    set @SQLCommand = 'execute spWebGetNeueBestellNummer'
    set @SQLParameter = '@BestellNr int OUTPUT'
    execute
    sp_executesql @SQLCommand, @SQLParameter, @BestellNr=@Rueckgabewert OUTPUT 
    Print @Rueckgabewert

    Und bekomme folgende Fehlermeldung:

    Die Prozedur oder Funktion 'spWebGetNeueBestellNummer' erwartet den '@BestellNr'-Parameter, der nicht bereitgestellt wurde.

    Was mache ich falsch ?

    Gruß Peter

    Dienstag, 1. Juni 2010 08:46
  • Hallo Peter,

    versuch mal den einfachen Weg, die SP direkt aufzurufen und nicht so umständlich über dynamisches SQL (den Output Parameter müsstest Du bereits in @SQLCommand übergeben):

    CREATE PROCEDURE [dbo].[spWebGetNeueBestellNummer] @BestellNr int Out

    AS

        SET @BestellNr = 12345;

    GO

     

     

    Declare @BestellNr int

    execute [dbo].[spWebGetNeueBestellNummer] @BestellNr OUTPUT

     

    SELECT @BestellNr;

     


    Olaf Helper ----------- * cogito ergo sum * errare humanum est * quote erat demonstrandum * Wenn ich denke, ist das ein Fehler und das beweise ich täglich http://olafhelper.over-blog.de
    Dienstag, 1. Juni 2010 08:58
  • Hallo Peter,

    das Prozedur-Gegenstück zu dem Aufruf - etwas gekürzt:

    CREATE PROCEDURE dbo.iv_InventurBelegFetch
    (
      @InventurNr   smallint,
      @BelegNr    int = NULL OUT,
      @BelegPosNr   smallint = NULL OUT
    )
    /***
      Name:    iv_InventurBelegFetch
      Date:    15.11.2001
      Parameter:
        @InventurNr  smallint IN
          Nummer der Inventur
        @BelegNr  int IN, OUT
          Abzurufende BelegNr
        @BelegPosNr  int IN, OUT
          Abzurufende Beleg Positions Nr
      Return:
        0  OK
        1  Fehler (auch gesperrte Inventur)
      Description:
        Liefert die nächste Beleg Nr einer Inventur.
        Dies erhöht gleichzeitig die Belegnummer im Inventursatz,
        so dass ein Aufruf nur bei echter Nutzung geschehen sollte.
    
        Bei geperrter Inventur wird ein Fehler und NULL geliefert
    ***/
    AS
      SET NOCOUNT ON
    
      -- Aus iv_Inventur
      DECLARE @Inventur_SperreKZ    tinyint,
          @Inventur_BelegNr    int
    
      BEGIN TRAN iv_InventurBelegFetch
    
      -- Inventur muss vorhanden und darf nicht gesperrt sein
      SELECT @Inventur_SperreKZ = SperreKZ,
        @Inventur_BelegNr = BelegNr
      FROM dbo.iv_Inventur WITH (UPDLOCK)
      WHERE InventurNr = @InventurNr
      IF @@ERROR <> 0 GOTO RollbackExit
      IF @Inventur_SperreKZ IS NULL
      BEGIN
        RAISERROR(3000012, -1, 1, 'Inventur', 'Die Inventur ist nicht vorhanden.')
        GOTO RollbackExit
      END 
      IF @Inventur_SperreKZ > 0 
      BEGIN
        RAISERROR(3000012, -1, 1, 'Inventur', 'Die Inventur ist gesperrt.')
        GOTO RollbackExit
      END 
    
      -- Beleg Nummer vergeben
      IF ISNULL(@BelegNr, 0) <= 0
      BEGIN
        -- Nächste Beleg-Nummer abrufen
        SET @BelegNr = @Inventur_BelegNr + 1
        -- Bei neuer Nummer mit 1 beginnen
        SET @BelegPosNr = 1
    
        UPDATE dbo.iv_Inventur 
        SET BelegNr = @BelegNr
        WHERE InventurNr = @InventurNr
        IF @@ERROR <> 0 GOTO RollbackExit
      END 
      -- ... gekürzt ... 
      COMMIT TRAN iv_InventurBelegFetch
      RETURN 0
    
    RollbackExit:
      IF @@TRANCOUNT > 0 ROLLBACK TRAN iv_InventurBelegFetch
      RETURN 1
    GO
    GRANT EXECUTE ON dbo.iv_InventurBelegFetch TO public
    GO
    Gruß Elmar

     

    Dienstag, 1. Juni 2010 13:07
    Beantworter
  • So, dann muß ich jetzt nur noch die ASP-Seiten dazu bringen, den Parameter auch auszulesen. Wie mache ich das am einfachsten ?

    Nachstehend mal ein paar Codeschnibbel, mit denen ich hier herumexperimentiere:

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

    DIM lanr, rslnr, cmd, dDate
    DIM RParameter
    Set cmd = Server.CreateObject("ADODB.Command")
    Set rs = Server.CreateObject("ADODB.Recordset")
    'Set RParameter = cmd.CreateParameter("Rueckgabeparameter", adBigInt, adParamOutput)
    Set RParameter = cmd.CreateParameter("Rueckgabeparameter", 20, 2)
    cmd.ActiveConnection = con
    cmd.CommandText = "spWebGetNeueBestellNummer @BestellNr OUTPUT"
    cmd.CommandType = 4 'adCmdStoredProc
    rs.CursorLocation = 3 'adUseClient
    rs.Open cmd
    DIM strNeuBestellNr
    strNeuBestellNr = @BestellNr
    rs.Close

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

    Dieses Segment ist noch fehlerhaft, derzeit kann ich die Seite, auf der diese Codeteile implementiert wurden, nicht aufgerufen werden.

    Wo ist mein Fehler?

    Gruß Peter

    Dienstag, 1. Juni 2010 14:23
  • Hallo Peter,

    da Du den Parameter als Skalarwert zurück erhälst, brauchst Du kein RecordSet. Bei der Parameter-Definition kannst Du angeben, das die Direction=OUTPUT ist, dann steht der Wert nach cmd.Execute() im Value des Parameters zur Verfügung:

    Public Sub test()

        Dim con As ADODB.Connection

        Dim cmd As ADODB.Command

       

        Set con = New Connection

        con.ConnectionString = "Provider=SQLNCLI10;Server=.;Database=AdventureWorks;Trusted_Connection=yes;"

        con.Open

       

        Set cmd = New Command

        cmd.ActiveConnection = con

        cmd.CommandText = "spWebGetNeueBestellNummer"

        cmd.CommandType = adCmdStoredProc

        cmd.Parameters("@BestellNr").Direction = adParamOutput

        cmd.Parameters("@BestellNr").Type = adInteger

       

        Call cmd.Execute

        'Ergebnis ausgeben

        Debug.Print cmd.Parameters("@BestellNr").Value

       

        cmd.ActiveConnection = Nothing

        Set cmd = Nothing

        con.Close

        Set con = Nothing

       

    End Sub

     


    Olaf Helper ----------- * cogito ergo sum * errare humanum est * quote erat demonstrandum * Wenn ich denke, ist das ein Fehler und das beweise ich täglich http://olafhelper.over-blog.de
    Mittwoch, 2. Juni 2010 05:13
  • Hallo Peter,

    Parameter mußt Du wie von mir und Olaf gezeigt über die Parameter Collection bekanntmachen.
    Was das Verwenden von Konstanten in klassischem ASP angeht, siehe
    http://www.asp101.com/articles/john/typelibs/default.asp

    Bei der Verwendung von Ausgabe-Parametern muß man zudem beachten,
    dass sie erst nach dem Schließen des letzten Recordsets (Resultset) zur Verfügung stehen.
    ADO erzeugt im Standard immer ein Recordset, was durch die Angabe von

     .Execute Options:=adExecuteNoRecords

    unterdrückt werden kann.
    Im allgemeinen sollte man auf ein Mischen von Recordset(s) und Ausgabe-Variablen verzichten.
    Und dazu ist die Angabe von SET NOCOUNT ON in solchen Prozeduren notwendig,
    denn ansonsten erzeugt der SQL Server (ggf. leere) Recordsets für jede DML Anweisung
    (auch INSERT/UPDATE/DELETE).

    Mehr siehe: How To Process Multiple Recordsets and Messages in ADO
    Auch mal wichtig: PRB: Recordset Does Not Open with A Stored Procedure that Returns a High Severity Error

    Gruß Elmar

    Mittwoch, 2. Juni 2010 09:01
    Beantworter
  • Hier mal der aktuelle Stand:

    Dank Eurer Hilfe konnte ich erfolgreich die BestellNr auslesen

    Ich hab zwar noch Probleme, mit Scope_Identity oder Ident_Current die Bestell_Nr zu ermitteln, aber wenn ich einen select max(BestellNr) from tabelle verwende, funktioniert es schon mal

    Die Lösung(en) entstammen nun vielen Posts aus diesem Thread, wie soll ich jetzt sinnvoll die Antwort markieren ?

    An dieser Stelle herzlichen Dank für Eure Hilfe; Ihr habt mir echt weitergeholfen !

    Viele Grüße

    Montag, 14. Juni 2010 09:05
  • Hallo Peter,

    ein SELECT MAX() ist im allgemeinen die schlechtere Lösung,
    da bei parallen Zugriffen zum einen nicht gesagt ist das man
    "seinen" Datensatz bekommt. Zum anderen ist das Konstrukt
    anfällig für Blockierungen.

    Wenn die Nummer nicht erscheint (auch bei adParamOutput)
    schau, ob Du SET NOCOUNT ON am Beginn der Prozedur hast.
    Denn Ausgabeparameter stehen immer erst nach dem letzten
    Recordset (Resultset) zur Verfügung.

    Gruß Elmar

    P. S. Die Antwortmarkierungen hat Robert ja schon gesetzt.
    Ansonsten hake da ab, wo Dir der Sinn danach ist - ggf.
    kannst Du die hilfreichen Antworten über die zusätzliche
    Schaltfläche links oben markieren.
    Ich für meinen Teil bin kein Punktesammler und mir reicht
    ein gelegentliches positives Feedback als solches :-)

    Montag, 14. Juni 2010 11:36
    Beantworter
  • Hallo zusammen,

    so wie es aussieht, waren wir wohl alle gemeinsam auf 'nem falschen Dampfer unterwegs.

    Also, ich habe nun versucht, meine behelfsmäßig geänderte StoredProc mit select max(BestellNr) from tabelle wieder in ein select ident_current('Tabelle') zu ändern, um dann weiter in Richtung Scope_Identity zu gehen.

    Im SQLSMS funktionierte die Befehlskette korrekt; auf der Webseite jedoch nicht. Der einzige Unterschied ist der verwendete User; als ich auf der Webseite den Verbindungs-User probeweise auf SA geändert habe, funktionierte sie auf Anhieb.

    Also, der User, der die Webseite mit der Datenbank verbindet, ist ein in den Rechten dramatisch gestutzter User (aus Sicherheitsaspekten). Welches Recht muß ich denn nun diesem User zusätzlich einräumen, daß er Ident_Current oder besser noch Scope_Identity verwenden kann ? Ein Betreiben der Webseite mit SA als Verbindungsuser kommt nicht in Frage.

    Viele Grüße

    Peter

    • Als Antwort markiert PHundhausen Dienstag, 27. Juli 2010 12:35
    Dienstag, 15. Juni 2010 10:25
  • Hallo Peter,

    für Ident_Current reicht es völlig aus, wenn man zumindest SELECT Rechte auf der Tabelle; Vermerk dazu habe ich in der Doku nicht gefunden, aber es ausprobiert und ist ja auch (fast) logisch; man muss zumindest Daten aus der Tabelle lesen dürfen, um auch den letzten Wert erfahren zu dürfen. Mit Scope_Identity ist es genaus so. "Nur" INSERT Rechte gehen ebenso.

    Mit MAX() zu arbeiten, wird igendwann mal daneben gehen, Elmar hatte es ja auch schon gesagt. Eine weitere Option wäre, mit der OUTPUT Klause des INSERT Befehles zu arbeiten, um die ID(s) zu ermitteln.

     


    Olaf Helper ----------- * cogito ergo sum * errare humanum est * quote erat demonstrandum * Wenn ich denke, ist das ein Fehler und das beweise ich täglich http://olafhelper.over-blog.de
    Dienstag, 15. Juni 2010 11:12
  • Hallo Olaf,

    in der Tat hat es ausgereicht, dem Benutzer auf die ID-Spalte ein Select-Recht einzuräumen und schon funzt alles wieder wie gehabt. Ich habe sogar schon mal frische Kopien erzeugt, die das ganze obige Herumgeändere nicht enthalten und siehe da, nach setzen dieses Rechts scheint die Seite auf Anhieb zu funzen :-)

    Werde mich jetzt mal weiteren Tests auf Funktionalität widmen ...

    Nochmal vielen Dank für Eure Hilfe !

    Peter

    Dienstag, 15. Juni 2010 14:14
  • Hallo Peter,

    da Du von SQL Server 2000 auf 2008 migrierst, schau Dir an:
    Konfigurieren der Sichtbarkeit von Metadaten
    denn (schon mit SQL Server 2005) wurde dort einiges geändert,
    und nicht mehr jeder kriegt alles zu sehen - Was bei einer Website
    i. a. auch empfehlenswert ist.

    Für die Ausführung von Prozeduren, wäre wichtig die EXECUTE AS Klausel
    (dort auch den Links in anderen Ressourcen folgen)

    Gruß Elmar

    Mittwoch, 16. Juni 2010 07:48
    Beantworter