none
Gestire eventi su tabelle di SQL Server 2017 RRS feed

  • Domanda

  • In un database sul SQL Server 2017 ho una tabella con il campo: IDOrdini, DataOrdine, DataLavorazione, DataSpedizione.
    La logica della tabella è:
    IDOrdini int identity(1,1) not null primary key clustered;  
    la DataOrdine sia sempre pari o successiva a se stessa, record dopo record (esempio se il record 1 ha 01/01/2017, il record 2 non può avere come data il 31/12/2016 e così gli altri record);  
    la DataLavorazione sia sempre pari o successiva alla DataOrdine;
    la DataSpedizione sia sempre pari o successiva alla DataLavorazione.

    La seconda e la terza condizione l'ho risolta con un CONSTRAINT CHECK, mettendo DataLavorazione >= DataOrdine ed in un altro CONSTAINT CHECK DataSpedizione >= DataLavorazione.
    Il problema c'è con la prima condizione.
    Ci vuole un TRIGGER (o STORED PROCEDURE ??) che riga dopo riga, mi controlli l'inserimento della DataOrdine, che sia sempre pari o successiva a se stessa.

    In un esempio su Access, con lo stesso database, il problema l'ho risolto creando una query come questa:  SELECT Max([DATARIO 3].[DATA ORDINE]) AS [MaxDiDATA ORDINE] FROM [DATARIO 3];
    e creandoci una maschera, con al centro il campo [MaxDiDATA ORDINE].
    Poi nella maschera con cui gestisco gli input delle tre date, sul campo DataOrdine, in Proprietà - Dati - Valido se - ho scritto: >= (tutta la query di prima).
    Con Access funziona bene, a parte problemi di refresh e requery della maschera creata sulla query.

    Tornando al TRIGGER, un piccolo aiuto ?

    Sul web ho trovato questo link: https://docs.microsoft.com/it-it/sql/t-sql/statements/create-trigger-transact-sql
    Può essere utile in attesa che trovo libri (anche in inglese) sui TRIGGER e STORED PROCEDURES ??

    P.S.: ho acquistato il libro T-SQL Fundamentals. Lo sto studiando, ma la programmazione con Trigger e Stored Procedures è appena accennata.  Non appena lo finisco, ne compro un altro più avanzato.

    Cordiali saluti.

    mercoledì 1 novembre 2017 10:02

Risposte

  • Ciao, 

    Non userei un trigger ma una Stored Procedure. La motivazione, in parte anche personale, è data dal fatto che un controllo prima dell'inserimento si addice di più ad un flusso che le stored procedure possono offrirti, mentre i trigger li lascerei ad azioni automatiche a fronte di un evento. Sembrano la stessa cosa da come le ho descritte ma concettualmente sono piuttosto differenti.

    Venendo alla realizzazione, farei una cosa del genere:

    CREATE PROCEDURE InserimentoData @DataNuovoOrdine      DATETIME,
                                     @DataNuovaLavorazione DATETIME,
                                     @DataNuovaSpedizione  DATETIME
    AS
      BEGIN
          DECLARE @DataUltimoOrdine AS DATETIME
    
          SELECT @DataUltimoOrdine = Max(dataordine)
          FROM   tabella
    
          IF @DataUltimoOrdine < @DataNuovoOrdine
            BEGIN
                INSERT INTO tabella
                            (dataordine,
                             datalavorazione,
                             dataspedizione)
                VALUES      (@DataNuovoOrdine,
                             @DataNuovaLavorazione,
                             @DataNuovaSpedizione)
    
                PRINT 'Inserimento avvenuto correttamente.'
            END
          ELSE
            PRINT 'La nuova data è meno recente di una già presente a database.'
      END

    Spero di averti aiutato,

    Gabriele

    PPS: più che un libro ti suggerirei, dal punto di vista pratico, di seguire le doc di Microsoft che hai postato e di fare tanta pratica. I libri in questo caso possono tornarti davvero utili qualora decidessi di approfondire il discorso dei piani di esecuzione delle query e/o delle stored procedures.


    • Modificato Gabriele Etta mercoledì 1 novembre 2017 15:30
    • Contrassegnato come risposta RobertIt69 giovedì 2 novembre 2017 11:36
    mercoledì 1 novembre 2017 10:27

Tutte le risposte

  • Ciao, 

    Non userei un trigger ma una Stored Procedure. La motivazione, in parte anche personale, è data dal fatto che un controllo prima dell'inserimento si addice di più ad un flusso che le stored procedure possono offrirti, mentre i trigger li lascerei ad azioni automatiche a fronte di un evento. Sembrano la stessa cosa da come le ho descritte ma concettualmente sono piuttosto differenti.

    Venendo alla realizzazione, farei una cosa del genere:

    CREATE PROCEDURE InserimentoData @DataNuovoOrdine      DATETIME,
                                     @DataNuovaLavorazione DATETIME,
                                     @DataNuovaSpedizione  DATETIME
    AS
      BEGIN
          DECLARE @DataUltimoOrdine AS DATETIME
    
          SELECT @DataUltimoOrdine = Max(dataordine)
          FROM   tabella
    
          IF @DataUltimoOrdine < @DataNuovoOrdine
            BEGIN
                INSERT INTO tabella
                            (dataordine,
                             datalavorazione,
                             dataspedizione)
                VALUES      (@DataNuovoOrdine,
                             @DataNuovaLavorazione,
                             @DataNuovaSpedizione)
    
                PRINT 'Inserimento avvenuto correttamente.'
            END
          ELSE
            PRINT 'La nuova data è meno recente di una già presente a database.'
      END

    Spero di averti aiutato,

    Gabriele

    PPS: più che un libro ti suggerirei, dal punto di vista pratico, di seguire le doc di Microsoft che hai postato e di fare tanta pratica. I libri in questo caso possono tornarti davvero utili qualora decidessi di approfondire il discorso dei piani di esecuzione delle query e/o delle stored procedures.


    • Modificato Gabriele Etta mercoledì 1 novembre 2017 15:30
    • Contrassegnato come risposta RobertIt69 giovedì 2 novembre 2017 11:36
    mercoledì 1 novembre 2017 10:27
  • Grazie dell'aiuto.
    Ho copiato la stored procedure nel Visual Studio 2017. Nessun errore. Poi da li l'ho trasferita nel SQL Server 2017.
    Poi ho creato una piccola stored procedure:

    CREATE PROCEDURE AvvioSP
    AS
    EXEC dbo.sp_DataOrdineNuovo --questa Stored Procedure è quella scritta sopra
    @DataNuovoOrdine = '20171101',
    @DataNuovaLavorazione = '20171102',
    @DataNuovaSpedizione = '20171102'
    GO

    per provare il funzionamento della precedente stored procedure.
    La prova l'ho fatta con il Management Studio.
    Funziona tutto bene, sia l'inserimento delle date in tabella che i messaggi, sia di buon esito quando la DataOrdine  è maggiore o uguale alla DataUltimoOrdine, che di errore quando la DataOrdine è minore della DataUltimoOrdine.  Il problema è che le date sono "STATICHE", mentre avrei bisogno che i valori  @Data siano collegati agli input da tastiera.

    Poi ho provato con quest'altra SP:

    CREATE PROCEDURE AvvioSP
    AS
    EXEC dbo.sp_DataOrdineNuovo --questa Stored Procedure è quella scritta sopra
    @DataNuovoOrdine = DataOrdine,
    @DataNuovaLavorazione = DataLavorazione,
    @DataNuovaSpedizione = DataSpedizione
    GO

    Ma non funziona niente.

    Rimane da definire il collegamento automatico tra stored procedure e maschera di Access, dato che l'input lo faccio da Access.
    Ho fatto delle prove con la maschera di Access (creata su tabella collegata con il SQL Server), ma è come se la stored procedure fosse assente.  Non c'è il controllo sulle date che mi serve.

    Cordiali saluti.

    giovedì 2 novembre 2017 08:22
  • Ciao,

    Ora che sappiamo che la SP risponde alle tue esigenze, puoi provare a rifarti a questo thread per avere una guida su come collegare le maschere di Access alle SP. In ogni caso, Access dovrebbe avere anche un wizard per guidarti in questo passaggio.

    Fammi sapere se ci sono dubbi,

    Gabriele

    giovedì 2 novembre 2017 08:36
  • Ho copiato il codice VBA del link nel file di Access, dove ho le tabelle collegate al SQL Server 2017.
    In un modulo della maschera, costruita sulla tabella collegata al Server, ho riportato il codice VBA, scrivendo alcune cose legate al mio DB, cioè nome server, nome database.
    ecco il codice completo:
    ---------------------------------
    Private Sub AccessSQL()
    Dim Conn As ADODB.Connection
    Dim Cmd As ADODB.Command
    Dim Rs1 As ADODB.Recordset
    Dim strConn As String

    'Crea la connessione String
        strConn = "Provider=SQLOLEDB.1;" & "Data Source=PC\SQLEXPRESS01; Initial Catalog = Primodatabase2017;" & "Integrated Security=SSPI"
    'Stabilisce la connessione
        Set Conn = New ADODB.Connection
            Conn.Open strConn
    'Apre il recordset
        Set Cmd = New ADODB.Command
            Cmd.ActiveConnection = Conn
            Cmd.CommandText = "dbo.sp_DataOrdineNuovo"
            Cmd.CommandType = adCmdStoredProc
            Cmd.Parameters.Refresh
            Cmd.Parameters(1).Value = [dbo_TabellaOrdiniClienti].[txtDataOrdine]
            Set Rs1 = Cmd.Execute()
            Rs1.MoveFirst
        Do Until Rs1.EOF = True
            MsgBox Rs1.Fields(2)
            Rs1.MoveNext
        Loop
    'Chiude la connessione
        Close Connection
        Rs1.Close
        Set Rs1 = Nothing
    End Sub
    --------------------
    Poi ho inserito un bottone sulla maschera, che ha il codice VBA, che dovrebbe attivare la stored procedure presente sul SQL Server 2017.

    Quando clicco esce l'errore:
    errore di runtime 3704
    l'operazione non è consentita se l'oggetto è chiuso.
    ------------------------------

    Forse il codice VBA non riesce ad accedere al server ?
    In corrispondeza della stringa di connessione ho:
    strConn = "Provider=SQLOLEDB.1;" & "Data Source=PC\SQLEXPRESS01; Initial Catalog = Primodatabase2017;" & "Integrated Security=SSPI"

    Poi, ho provato il debug del codice, ma esce come errore il non riconoscimento della maschera, in questo punto:
    Cmd.Parameters(1).Value = me.[txtDataOrdine]
    Il nome della maschera non lo trovo nelle sue proprietà.
    Ho provato a mettere altri nomi tipo:
    Cmd.Parameters(1).Value = [dbo_TabellaOrdiniClienti].[txtDataOrdine]
    ma non funziona.

    Comunque, a me serveribbe un codice VBA che quando digito nel campo DataOrdine della maschera una data precedente a se stessa di un record precedente, mi deve impedire l'immissione di quel dato. 
    Ciò lo deve fare senza che io controlli cliccando su un bottone sulla maschera.
    giovedì 2 novembre 2017 10:42
  • Ciao,

    Per il codice VBA dovresti chiedere nella sezione apposita: ciò serve a mantenere il focus sulla problematica del thread descritta nel titolo.

    A presto,

    Gabriele

    giovedì 2 novembre 2017 10:54
  • Ok.

    Per questo thread approfondirò il discorso dei piani di esecuzione delle query e/o delle stored procedures con opportuni libri.

    Saluti.

    giovedì 2 novembre 2017 11:35
  • scusa ma secondo me ti basterebbe mettere una condizione IF sulla textbox nella maschera di access che segua una query sulla tabella andando a cercare il max(DataOrdine) e l'IF consenta l'immissione della data nella taxtbox solo se maggiore o uguale alla data estratta dalla query quindi potresti fare tutto in vba senza scomodare T-SQL con stored procedure o trigger.

    ciao


    Edoardo Benussi
    Microsoft MVP - Cloud and Datacenter Management
    e[dot]benussi[at]outlook[dot]it

    lunedì 6 novembre 2017 10:57
    Moderatore