Sostituzione campo tabella

di il
19 risposte

Sostituzione campo tabella

Buongiorno, io ho una tabella cosi formata
ARCHIVIO(ID*,Num_Doc_Origine,Num_Doc,Anno)
con
ID PK numerazione automatica,
Num_Doc_Origine alfanumerico (in quanto può contenere num, lettere e caratteri come / -)
Num_Doc numerico
Anno numerico

io ho compilato il Num_Doc_Origine e l'anno l'ho preimpostato a 2020, mentre il Num_Doc è vuoto ma ho bisogno di mettere in questo campo solo gli ultimi 5 caratteri di Num_Doc_Origine.

la tabella iniziale si presenta:
ID| Num_Doc_Origine | Num_Doc | Anno
1 | 2020/VE/00001 | 0 | 2020
2 | 2020/VE/00002 | 0 | 2020
.......

voglio però che la tabella mi esca:
ID| Num_Doc_Origine | Num_Doc | Anno
1 | 2020/VE/00001 | 00001 | 2020
2 | 2020/VE/00002 | 00002 | 2020
.......

per prendere i caratteri uso la seguente query:
SELECT RIGHT(Num_Doc_Origine,5)
FROM ARCHIVIO;

Problema.... Non so come far sostituire in automatico i campi in Num_Doc con in valori della query.

Spero di essermi spiegata.

Grazie,
Sara

19 Risposte

  • Re: Sostituzione campo tabella

    Salve Sara,
    la colonna [Num_Doc] e' basata su un tipo di dato "numerico" (come tu hai indicato), quindi NON potra' mai avere una valorizzazione "00001", "00002", etc, ma solo un valore numerico, e quindi 1, 2, n
    se necessiti di un tale tipo di valorizzazione, devi trasformare il tipo di dato di appoggio da int a char(5)/varchar(5) (meglio char) e quindi potrai popolare la colonna come da te richiesto...
    salutoni romagnoli
    --
    Andrea
  • Re: Sostituzione campo tabella

    ... al massimo puoi vederlo formattato se la tua versione di sqlserver supporta format

    select format(123,'00000')
  • Re: Sostituzione campo tabella

    Salve @spintux,
    ma questa sarebbe solamente una "proiezione" del dato (che potrebbe anche essere sufficiente), ma non un'effettiva serializzazione... vedi mai la necessita' di vincoli o altro...
    quindi, direi a Sara che deve "cambiare" il tipo di dato se necessita di valorizzare la colonna come "stringa", diversamente, se basta la formattazione (sia essa con format(n, 'format') oppure con manipolazione di stringhe se la versione di SQL Server < 2014, allora puo' tenere il numerico, e per valorizzare il corrente set di dati le basta eseguire un update impostando [Num_Doc] = CONVERT( int, RIGHT(Num_Doc_Origine,5) ) (o TRY_CONVERT se disponibile)...
    salutoni romagnoli
    --
    Andrea
  • Re: Sostituzione campo tabella

    Grazie mille adesso provo subito
  • Re: Sostituzione campo tabella

    Perfetto ho modificato il campo Num_Doc e ho eseguito la query:
    UPDATE ARCHIVIO
    SET Num_Doc =(RIGHT(Num_Doc_Origine,5) ) ;

    e funziona.

    Grazie milleeee
    Sara
  • Re: Sostituzione campo tabella

    Buongiorno,
    altra ipotesi...
    per sostituire sempre lo stesso campo (Num_Doc) ma che è formattato come segue
    numero/2020 (il numero non ha una lunghezza specifica può variare da 1 a x cifre)

    ho bisogno dei valori prima di /2020.
    La sintassi qual è?

    Grazie
    Sara
  • Re: Sostituzione campo tabella

    Prendi spunto da qui ed usa quello che già sai:
    
    select CHARINDEX('/', T)
    from (select '123/2020' as T) q
    
    EDIT
    anzi questa è meglio se sono possibili altri separatori diversi da "/"
    
    select patindex( '%[^0-9]%', T)
    from (select '123/2020' as T) q
    
  • Re: Sostituzione campo tabella

    Ciao,
    grazie per lo spunto, dopo lo provo.

    Comunque per rimpiazzo (diciamo cosi) ho utilizzato la query di seguito:
    UPDATE ARCHIVIO
    SET Num_Doc = (REPLACE(Num_Doc_Origine,"/2020",""));

    magari non è proprio la formula più corretta ma è servita al mio problema!

    Grazie e buona giornata
    Sara
  • Re: Sostituzione campo tabella

    Se è sempre "/2020" va benissimo
  • Re: Sostituzione campo tabella

    In realtà nel campo Num_Doc_Origine ci sono anche altri valori che però non devono essere toccati quindi ho fatto un "filtro" con la condizione WHERE.

    Sara
  • Re: Sostituzione campo tabella

    Buongiorno,
    data sempre la tabella iniziale con il Num_Doc, avrei bisogno di controllare se c'è un salto di numerazione e se ci sono duplicati.
    Nel caso in cui ci fossero salti avrei bisogno di identificare il numero saltato, cosa analoga per i duplicati.

    tbl iniziale:
    2020/VE/000001
    2020/VE/000002
    2020/VE/000003
    2020/VE/000004
    2020/VE/000006
    2020/VE/000006

    vorrei visualizzare:
    - documenti mancanti=1
    - numero documento mancante=000005

    - documenti duplicati=1
    - numero documento duplicato=000006

    Qualche idea su come fare?

    Grazie,
    Sara
  • Re: Sostituzione campo tabella

    Salve,
    la 2* richiesta e' tendenzialmente facile, basta utilizzare un raggruppamento con filtro sulla cardinalita' dello stesso, quindi, trivialmente,
    
    ... TABLE dbo.t (
    	Id int NOT NULL
    	);
    GO
    INSERT INTO dbo.t 
    	VALUES ( 1 ), ( 2 ), ( 3 ), ( 4 ), ( 5 )
                           , ( 3 ), ( 4 );  -- <- doppioni
    GO
    SELECT t.[Id]
    	FROM dbo.t t
    	GROUP BY t.[Id]
    		HAVING COUNT(*) > 1
    	ORDER BY t.[Id];
    --<-----------
    Id
    -----------
    3
    4    
    
    la prima delle 2 domande ha invece soluzioni "complicate" dal punto di vista computazionale...
    ragionando in termini di insiemi, dobbiamo confrontare il set "reale" con un set dinamico e ricavarne gli eventuali gap...
    spesso, nei database, esistono tabelle apposite di appoggio, tabelle costituite dalla serie dei numeri interi da 0 a n (dove "n" e' un numero bello grande) al fine proprio di risolvere questa tipologia di problematiche...

    in assenza di queste, possiamo produrre ad esempio tramite Common Table Epression ricorsiva un set in questo senso, da utilizzare poi in JOIN per l'individuazione dei gap eventualmente presenti.
    possiamo quindi ad esempio basarci sul bellissimo spunto di Itzik Ben Gan, MVP di SQL Server e geniale mente matematica, che utilizzando una serie di Common Table Expressions innestate con operazioni di cross join, genera "al volo" il nostro SET composto dalla serie numerica finita e completa...
    utilizzando piu' CTE si puo' incrementare la cardinalita' di tale proiezione di appoggio, ma oltre la presente esemplificazione si deve cambiare dominio e passare al tipo di dato bigint...
    ricordo che nel caso la cardinalita' della tabella di origine da confrontare base sia gia' alta, questa operazione e' dispendiosa e, nel caso, conviene non operare "al volo" ma creare effettivamente la tabella numerica di appoggio gia' popolata definitivamente sul database o su altro database di appoggio..
    il popolamento del set ausiliario e' ovviamente pesante se va eseguito spesso, ed in questo caso sarebbe bene disporre della tabella numerica ausiliaria, ma se e' un'operazione "una tantum", si puo' anche fare:

    torniamo quindi all'implementazione, e sempre trivialmente continuiamo dal precedente, e popoliamo la tabella originale da 1 a 10k
    
    PRINT 'caricamento iniziale'; 
    
    DECLARE @i int = 1;
    WHILE @i <= 10000 BEGIN
    	INSERT INTO dbo.[t] VALUES ( @i );
    	SET @i += 1;
    END;
    GO
    


    e qui provvediamo prima alla generazione del set di serie progressiva numerica da 1 a n dove n == al "max" della tabella da "confrontare", e quindi proiettiamo il LEFT JOIN del risultato con la tabella di "origine",
    
    GO
    DECLARE @min int;
    SELECT @min = MAX(t.[Id])
    	FROM [dbo].[t] t
    
    SET @min = ISNULL(@min, 1);
    SET @min += 0;
    
    -- ottiene tabella di numeri
    WITH Nbrs_4( n ) AS ( 
    	SELECT 1 UNION SELECT 0 ),
    Nbrs_3( n ) AS ( 
    	SELECT 1 FROM Nbrs_4 n1 CROSS JOIN Nbrs_4 n2 ),
    Nbrs_2( n ) AS ( 
    	SELECT 1 FROM Nbrs_3 n1 CROSS JOIN Nbrs_3 n2 ),
    Nbrs_1( n ) AS (
    	SELECT 1 FROM Nbrs_2 n1 CROSS JOIN Nbrs_2 n2 ),
    Nbrs_0( n ) AS ( 
    	SELECT 1 FROM Nbrs_1 n1 CROSS JOIN Nbrs_1 n2 ),
    Nbrs  ( n ) AS ( 
    	SELECT 1 FROM Nbrs_0 n1 CROSS JOIN Nbrs_0 n2 ),
    -- scarta i numeri eccessivi
    cUsed AS (
    	SELECT n
    		FROM ( 
    			SELECT ROW_NUMBER() OVER (ORDER BY n) 
    				FROM Nbrs 
    			) D ( n )
    		WHERE n <= @min
    	)
    -- avendo il set seriale completo da 1 a n, dove n == MAX(t.[Id]), possiamo evidenziare gli eventuali gap
    SELECT c.[n] AS [Numero Assente]
    	FROM cUsed c
    		LEFT JOIN [dbo].[t] t ON t.[Id] = c.[n]
    	WHERE t.[Id] IS NULL
    	ORDER BY c.[n];
    


    se eseguiamo "ora" il codice, avremo come risultato un empty set in quanto la serie della tabella di origine e' completa, quindi procediamo con
    
    DELETE [dbo].[t] 
    	WHERE ([Id] % 255 = 0);
    
    al fine di cancellare 1 riga ogni 255 (togliamo 39 righe), e rieseguendo la query di cui sopra, troveremo tutti i gap risultanti.

    salutoni romagnoli
    --
    Andrea
  • Re: Sostituzione campo tabella

    Intanto grazie.

    Io ho provato a fare così però non mi tiene conto della Serie_Doc

    asql ha scritto:


    
    ... TABLE dbo.t (
    	Id int NOT NULL
    	);
    GO
    INSERT INTO dbo.t 
    	VALUES ( 1 ), ( 2 ), ( 3 ), ( 4 ), ( 5 )
                           , ( 3 ), ( 4 );  -- <- doppioni
    GO
    SELECT t.[Id]
    	FROM dbo.t t
    	GROUP BY t.[Id]
    		HAVING COUNT(*) > 1
    	ORDER BY t.[Id];
    --<-----------
    Id
    -----------
    3
    4    
    
    Cioè...

    I dati di partenza sono:
    Serie_Doc / Num_Doc
    0 / 1
    0 / 2
    0 / 3
    1 / 1
    1 / 2
    1 / 2


    Ho usato questa qry:
    SELECT Num_Doc, Serie_Doc
    FROM ARCHIVIO
    WHERE Num_Doc IN (SELECT Num_Doc
    FROM ARCHIVIO
    GROUP BY Num_Doc
    HAVING COUNT(*)>1
    ORDER BY Num_Doc;)
    GROUP BY Serie_Doc, Num_Doc;

    Ed il risultato finale è come segue:
    Serie_Doc / Num_Doc
    0 / 1
    0 / 2
    0 / 3
    1 / 1
    1 / 2

    Quindi mi mostra i numeri 1,2 e 3 della serie 0 anche se non dovrebbe perchè in quella serie non sono duplicati. E per la serie 1 mi mostra i numeri 1 e 2, anche se l'unico duplicato qui è il 2.

    Io vorrei proprio che il risultato della qry fosse:
    Serie_Doc / Num_Doc
    1 / 2

    Sara.
  • Re: Sostituzione campo tabella

    Salve Sara,
    
    .... TABLE [dbo].[t] (
    	[Serie_Doc] varchar(10),
    	[Num_Doc] int
    	);
    GO
    INSERT INTO [dbo].[t]
    	VALUES ( '0', 1 ), ( '0', 2 ), ( '0', 3),
    			( '1', 1 ), ( '1', 2 ), ( '1', 2 ); -- {1 | 2} e' un doppione
    GO
    SELECT t.[Serie_Doc], t.[Num_Doc]
    	FROM [dbo].[t] t
    	GROUP BY t.[Serie_Doc], t.[Num_Doc]
    		HAVING COUNT(*) > 1
    	ORDER BY t.[Serie_Doc], t.[Num_Doc];
    --<------------
    Serie_Doc  Num_Doc
    ---------- -----------
    1          2
    
    e la tua query precedente, quindi, deve tenere in considerazione entrambi gli attributi, [Serie_Doc] e [Num_Doc].

    riscrivi il tutto, magari con una Common Table Expression ed una una JOIN,
    
    WITH cte AS (
      SELECT t.[Serie_Doc], t.[Num_Doc]
      	FROM [dbo].[t] t
      	GROUP BY t.[Serie_Doc], t.[Num_Doc]
      		HAVING COUNT(*) > 1
        )
        SELECT a.[Serie_Doc], a.[Num_Doc]
            FROM [Archivio] a
                JOIN cte c ON a.[Serie_Doc] = c.[Serie_Doc]
                    AND  a.[Num_Doc] = c.[Num_Doc]
            ORDER BY a.[Serie_Doc], a.[Num_Doc];
    
    in questo modo puoi mettere in JOIN il sottoinsieme raggruppato dei doppioni con la tabella "principale" al fine di ottenere l'intera proiezione di riga come a te conviene...
    se invece NON ti servono altri attributi della tabella "principale", allora ti basta il codice del solo raggruppamento senza doversi correlare con la tabella "principale"...


    tra l'altro, ma non c'entra con il problema in questione, indica sempre gli oggetti con il nome completo, composto quindi da schema + nome, perche' l'assenza del "nome completo" e' uno dei presupposti per il quale il motore del "query analyzer" scarta i piani precompilati, quindi presumibilmente effettua una nuova compilazione del piano di esecuzione della query ad ogni sua esecuzione...

    salutoni romagnoli
    --
    Andrea
Devi accedere o registrarti per scrivere nel forum
19 risposte