giovedì 25 luglio 2019

Dimensione tabelle in Sql Server

Ci sono diversi modi per conoscere l'effettiva dimensione in Kb/Mb di una tabella

Usando Sql Server Management Studio è possibile cliccare con il tasto destro sul database, scegliere dal menu la voce Report, quindi la voce "Report Standard" e infine la voce "Spazio su disco utilizzato per tabella".


Sempre con Sql Server Management Studio, selezionare prima la voce "Tabelle" nell'elenco di sinistra. Nella finestra "Dettagli esplora oggetti", una volta visualizzate tutte le tabelle è possibile indicare quali colonne vogliamo visualizzare. Fra le colonne che per default sono deselezionate ci sono : "Spazio utilizzato per i dati (KB)" e "Spazio utilizzato per gli indici (KB)"


L'ultimo modo per determinare lo spazio utilizzato dalle tabelle e degli indici di un database è quello di eseguire la seguente query (thanks Gianni GC Ceccanti 19/03/2021): 

select cast(Tabella as char(50)) as "Tabella", 
       max(Record) as "N. Record",  --max perché in base agli inidici cambia, il max corrisponde al totale sulla tabella
       sum(AllocatoTabellaMB) + sum(AllocatoIndiceMB) as "Totale Allocato (MB)", -- allocato su disco
       sum(AllocatoTabellaMB) as "Allocato Tabella (MB)", -- allocato su disco
       sum(AllocatoIndiceMB) as "Allocato Indice (MB)", -- allocato su disco
       sum(InutilizzatoMB) as "Inutilizzato (MB)" -- differenza tra spazio allocato e spazio utilizzato, quindi disponibile prima che SQLServera allochi nuovo spazio
  FROM (
      SELECT t.name AS "Tabella",
            p.rows as "Record",
            isnull( i.name , '_tabella_' ) as Tipo,
            (case when i.name is null then  CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) else 0 end) AS AllocatoTabellaMB,
            (case when i.name is not null then  CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) else 0 end) AS AllocatoIndiceMB,
            CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2) AS NUMERIC(36, 2)) AS InutilizzatoMB
       FROM sys.tables t
            INNER JOIN sys.indexes i ON t. object_id = i.object_id
            INNER JOIN sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
            INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
            LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id
      WHERE t.name NOT LIKE 'dt%' 
         AND t.is_ms_shipped = 0
         AND i.OBJECT_ID > 255 
      GROUP BY  t.name, s.name, p.rows, i.name
      ) as innertable
GROUP BY Tabella
ORDER BY sum(AllocatoTabellaMB) + sum(AllocatoIndiceMB) DESC, Tabella
La query precedente, qui sotto, non teneva conto degli indici:
SELECT 
    t.NAME AS TableName,
    s.Name AS SchemaName,
    p.rows AS RowCounts,
    SUM(a.total_pages) * 8 AS TotalSpaceKB, 
    CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS TotalSpaceMB,
    SUM(a.used_pages) * 8 AS UsedSpaceKB, 
    CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS UsedSpaceMB, 
    (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB,
    CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2) AS NUMERIC(36, 2)) AS UnusedSpaceMB
FROM 
    sys.tables t
INNER JOIN      
    sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN 
    sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN 
    sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN 
    sys.schemas s ON t.schema_id = s.schema_id
WHERE 
    t.NAME NOT LIKE 'dt%' 
    AND t.is_ms_shipped = 0
    AND i.OBJECT_ID > 255 
GROUP BY 
    t.Name, s.Name, p.Rows
ORDER BY 
    t.Name
Riferimenti : 
https://stackoverflow.com/questions/7892334/get-size-of-all-tables-in-database

lunedì 5 febbraio 2018

SQL Server Migration Assistant (SSMA)

SQL Server migration assistant (SSMA) è un tool Microsoft che facilità la migrazione da altri RDBMS verso Sql Server.

SSMA è disponibile per la migrazione dai seguenti RDBMS:
  • Access
  • Db2
  • MySql
  • Oracle
  • SAP ASE

La versione di Sql Server di destinazione dovrà essere una delle seguenti:
  • SQL Server 2008
  • SQL Server 2008 R2
  • SQL Server 2012
  • SQL Server 2014
  • SQL Server 2016
  • Azure SQL Database
  • SQL Server 2017 on Windows and Linux (Preview)


Il tool premette la migrazione di dati, schema, struttura tabelle, viste, indici e trigger.

Il tool permette di sincronizzare i due database per quanto riguarda gli oggetti presenti. Il mio utilizzo è stato solo quello di migrazione delle strutture delle tabelle, indici e dei dati.

Ho usato il tool per trasferire dai dati da Oracle 10 a Sql Server 2012 Express.
Inizialmente è necessario collegarsi al server Oracle e a quello SQL Server.

Per quanto riguarda Oracle è sufficiente indicare il server e le credenziali.
 Per quanto riguarda Sql Server, oltre a server e credenziali è necessario indicare anche il database di destinazione.



Nella finestra principale il tool visualizza tutti gli schema dell’istanza Oracle.


Per quanto riguarda le strutture dati è necessario eseguire i seguenti passi :
  •          Scegliere lo/gli schema Oracle da migrare
  •          Scegliere la funzione “Convert Schema” dal menu contestuale
  •          Scegliere il database Sql Server di destinazione
  •          Scegliere la funzione “Synchronize with database” dal menu contestuale


Per quanto riguarda i dati è necessario eseguire i seguenti passi :
  •         Scegliere lo/gli schema Oracle da migrare
  •         Scegliere la funzione “Migrate Data” dal menu contestuale


L’utilizzo normale del tool prevede che dato un database di Oracle, tutti i suoi schema vengano passato su un singolo database di Sql Server. Per questo motivo le tabelle di destinazione utilizzano lo stesso schema delle tabelle di origine.

Per cambiare il mapping dello schema è sufficiente selezionare lo schema di origine e cambiare il “target schema” nello “schema mapping” sulla destra dello schermo.
Quindi da database.schema a database.dbo

Nel caso si voglia trasferire ogni schema di Oracle su un database diverso di Sql Server è necessario creare un nuovo progetto di SSMA per ogni schema.

La pagina web di riferimento del tool :



lunedì 4 dicembre 2017

Creazione User in Sql Server

Per una installazione ho avuto necessità di gestire più utenti all'interno dello stesso database.

Quindi richiamare un dato con :
SELECT * FROM . invece del normale SELECT * FROM dove l'user dbo è sottinteso.

i comandi da eseguire sono i seguenti ( ho messo i comandi perché quando si creano 50 utenti si fa prima tramite i comandi che tramite l'SqlManagement) :


USE [master] 
GO
-- Creazione utente per il login a livella di istanza
CREATE LOGIN ['<login>'] WITH PASSWORD=N'<password>', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF 
GO

-- Da qui tutti i comandi sono specifici per il database
USE ['<Database>']
GO
-- Creazione utente del DB collegato all'utente di login
CREATE USER ['<user>'] FOR LOGIN ['<login>'] WITH DEFAULT_SCHEMA=['<schema>']
GO

-- Creazione Schema
CREATE SCHEMA ['<schema>'] AUTHORIZATION ['<user>']
GO

-- Aggiunta del ruolo db_ddladmin all'utente altrimenti non può creare e gestire le tabelle
EXEC sp_addrolemember N'db_ddladmin', N'<user>'
GO

Nel mio esempio reale '<login>','<password>','<user>' e '<schema>' avevano tutti lo stesso valore. (es. Ditta1)

Con questa struttura ho un solo database con tanti schema all'interno.

Con questo procedimento, per quanto riguarda Sigla, ho la stringa di connessione fatta così : 
DSN=DB1;UID=DITTA1;PWD=DITTA1;
DSN=DB1;UID=DITTA2;PWD=DITTA2;
ecc.

A livello di supporto una volta collegato al database DB1 posso lavorare con le tabelle usando :
SELECT * FROM DITTA1.DPCONFIG
Significa leggere la tabella DPCONFIG dello schema DITTA1 del database DB1

Aggiunta :
a seguito di un RESTORE DATABASE, dopo il CREATE LOGIN è sufficiente fare :

ALTER USER <user> WITH LOGIN=[<login>], DEFAULT_SCHEMA=[<schema>]

per riassociare l'utente del db all'utente dell'istanza 

mercoledì 15 febbraio 2017

Trasferimento dati fra versioni diverse di SQL Server

Come è risaputo su Sql Server non è possibile ripristinare un file di backup creato con una versione più recente.

Certe volte non è possibile neppure usare software di terze parti in quanto i due server non comunicano direttamente fra loro.

Sql Server Management Studio ci viene incontro. Permette infatti la creazione di script di creazione e di popolamento delle tabelle.

Si inizia sulla macchina su cui dobbiamo fare il backup, cliccando con il tasto destro sul database da copiare e scegliendo la voce "Tasks" e successivamente la voce "Generate Scripts".
A questo punto, tramite un wizard, viene richiesto se trasferire tutto il database o scegliere manualmente le tabelle/viste da trasferire.

Nella pagina successiva si può scegliere la destinazione del file che conterrà tutti comandi SQL.
Per default Management Studio esporta solo lo script per ricreare la struttura della tabella.
Premendo il tasto "Advanced" è possibile indicare che si vogliono anche i dati.
E' sufficiente impostare a "Schema and Data" la voce "Types of data to script".
Impostare anche a False la voce "Script of USE Database" se vogliamo importare i dati in un database con un nome diverso.
Impostando a True la voce "Script Indexes" vengono generate le istruzioni per la creazione degli indici collegati alle tabelle.
Al termine dell'operazione avremo un file .sql con tutte le istruzioni SQL per la creazione delle tabelle con i loro indici e il loro popolamento.

A questo punto è necessario copiare il file sulla macchina su cui si vuole ripristinare i dati, accedere al prompt dei comandi e digitare le seguenti istruzioni:
SQLCMD [-S server] [-U utente] [-P password] [-d database] [-i nome_file_sql]
Esempio:
SQLCMD -S localhost -U sa -P 12345678 -d DITTA1 -i c:\temp\ditta1.sql



venerdì 11 settembre 2015

Funzioni con parametri in SQL Server che restituiscono tabelle

In Sql Server è possibile creare delle funzioni passandogli dei parametri a avere in ritorno una tabella.
Una specie di vista con parametri

La sintassi è
CREATE FUNCTION ( )
RETURN TABLE AS
RETURN

SELECT * FROM
WHERE =@Parametro
)

Nel mio caso specifico avevo bisogno di una vista che passandogli il magazzino e gli estremi delle date mi restituisse le giacenze del magazzino e del periodo di date indicato



CREATE FUNCTION dbo.VDgaTest (@Magazzino CHAR(3),@DaData CHAR(8), @AData CHAR(8))
RETURNS TABLE
AS
RETURN
(
     select ARTICOLO,
     round(sum ( 
     case 
      when INVENTARIO =  '+'  then QUANTITA
      when INVENTARIO =  '-'  then QUANTITA*-1 
      when CARICO =  '+'  then QUANTITA    
      when CARICO =  '-'  then QUANTITA*-1
      when ACARICO =  '+'  then QUANTITA  
      when ACARICO =  '-'  then QUANTITA*-1
      when SCARICO =  '-'  then QUANTITA
      when SCARICO =  '+'  then QUANTITA*-1 
      when ASCARICO =  '-'  then QUANTITA 
      when ASCARICO =  '+'  then QUANTITA*-1
     end),4) GIACENZA
    from MOVIMAG
    where 1=1
    and DATA>= @DaData 
    and DATA<= @AData 
    and TIPO <>  '..' 
    AND MAGAZZINO=@Magazzino
    group by ARTICOLO
)

La funzione si richiama semplicemente con un :
SELECT * FROM vDgaTest('000','20150101','20150831')


martedì 28 luglio 2015

Backup Sql Server con giorno della settimana nel nome file

Il seguente script permette di effettuare il backup di tutti i database non di sistema, inserendo nel nome del file il giorno della settimana. In questo modo, con una schedulazione settimanale, avremo sempre sette backup distinti.

L'unica riga da variare è quella relativa al path di destinazione del backup.


DECLARE @name VARCHAR(50) -- database name  
DECLARE @path VARCHAR(256) -- path for backup files  
DECLARE @fileName VARCHAR(256) -- filename for backup  
DECLARE @fileDate VARCHAR(20) -- used for file name

 
-- specify database backup directory
SET @path = 'D:\ARCHIVIO\SIGLA\BackupSQL\'  

 
-- specify filename format
SELECT @fileDate = DATEPART(DW, GETDATE()) 

 
DECLARE db_cursor CURSOR FOR  
SELECT name 
FROM master.dbo.sysdatabases 
WHERE name NOT IN ('master','model','msdb','tempdb')  -- exclude these databases

 
OPEN db_cursor   
FETCH NEXT FROM db_cursor INTO @name   

 
WHILE @@FETCH_STATUS = 0   
BEGIN   
       SET @fileName = @path + @name + '_G' + @fileDate + '.BAK'  
       BACKUP DATABASE @name TO DISK = @fileName  WITH  INIT ,
          NOUNLOAD ,
          NOSKIP ,
          NOFORMAT 

 
       FETCH NEXT FROM db_cursor INTO @name   
END   

 
CLOSE db_cursor   
DEALLOCATE db_cursor

venerdì 12 giugno 2015

Rinumerazione cespiti - script sql

Il seguente script rinumera tutti i cespiti presenti in archivio

DECLARE @Codice CHAR(5)  
DECLARE @Categoria CHAR(3)
DECLARE @cmd NVARCHAR(500)  
DECLARE @Conta INT
DECLARE @ContaA CHAR(5)

DECLARE Categoria CURSOR FOR  
  SELECT distinct CATEGORIA FROM CESPITI  
  ORDER BY CATEGORIA

OPEN Categoria 
FETCH NEXT FROM Categoria INTO @Categoria
WHILE @@FETCH_STATUS = 0 BEGIN  
    SET @Conta = 0

    SET @cmd = 'DECLARE Cespiti CURSOR FOR  ' + 
               '    SELECT CODICE FROM CESPITI  ' +  
               '    WHERE CATEGORIA=' + '''' + @Categoria + '''' +  
               '    ORDER BY CODICE';  
    EXEC (@cmd)  

    OPEN Cespiti  
    FETCH NEXT FROM Cespiti INTO @Codice  
    WHILE @@FETCH_STATUS = 0 BEGIN  
           SET @Conta = @Conta + 1           
           SET @ContaA = Right('00000'+RTrim(LTrim(CAST(@Conta as CHAR(5)))),5)

           SET @cmd = 'UPDATE CESPITI SET CODICE=' + '''' + @ContaA + ''''+  ',' + 
                      ' CODPADRE=' + '''' + @ContaA + '''' + 
                      ' WHERE CATEGORIA=' + '''' + @Categoria + '''' +  
                      ' AND CODICE=' + '''' + @Codice + ''''
           EXEC (@cmd)  

           SET @cmd = 'UPDATE MOVCE SET CODCESPITE=' + '''' + @ContaA + ''''+  ',' + 
                      ' CODPADRE=' + '''' + @ContaA + '''' + 
                      ' WHERE CATEGORIA=' + '''' + @Categoria + '''' +  
                      ' AND CODCESPITE=' + '''' + @Codice + ''''
           EXEC (@cmd) 

           FETCH NEXT FROM Cespiti INTO @Codice  
    END  
    CLOSE Cespiti  
    DEALLOCATE Cespiti 

    -- Allinea il numeratore
    SET @Conta = @Conta + 1
    SET @ContaA = Right('00000'+RTrim(LTrim(CAST(@Conta as CHAR(5)))),5)
    SET @cmd = 'UPDATE NUCESP SET NUMEROCESP=' + '''' + @ContaA + '''' + 
                  ' WHERE CATEGORIA=' + '''' + @Categoria + ''''; 
    EXEC (@cmd) 


    FETCH NEXT FROM Categoria INTO @Categoria
end
CLOSE Categoria
DEALLOCATE Categoria