Login Login
MORE

WIDGETS

Widgets

Wanted articles
Who is online?
Article tools

MSSQL:Script Utili2

From Aino Wiki

Jump to: navigation, search

Ricerche

Testo in Stored Procedure e Funzioni

SELECT name
FROM   sys.procedures
WHERE  Object_definition(object_id) LIKE '%''MGM''%'

Oggetti: tabelle, etc

IF OBJECT_ID ('Contacts1', 'U') IS NOT NULL
DROP TABLE dbo.Contacts1;

Conversioni

Numeri da base a base

Da base N a decimale

CREATE FUNCTION dbo.fn_FromBasenTo10(@String varchar(20),@N int)
RETURNS BIGINT
AS
BEGIN
  DECLARE @Result AS BIGINT = 0,
    @basestring AS VARCHAR(100) = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
    @digit	AS CHAR,
    @pow	AS BIGINT = 0
 
  WHILE @pow < len(@String) BEGIN
    set @digit = substring(reverse(@String), @Pow+1,1)
    set @Result = @Result + (charindex(@Digit, @baseString) - 1) * power(@N, @pow)
    set @pow = @pow + 1
  END
  RETURN @Result
END
GO
--------------------- Uso --------------------
select dbo.fn_FromBasenTo10('001L9', 36) --Restituirà: 2061

Da base decimale a base 32

CREATE FUNCTION dbo.fn_FromBase10To36
(
    @Val BIGINT
)
RETURNS VARCHAR(9)
AS
BEGIN
    DECLARE @Result VARCHAR(9) = ''
 
    IF (@Val <= 0)
    BEGIN
        RETURN '0'
    END
 
    WHILE (@Val > 0)
    BEGIN
        SELECT @Result = CHAR(@Val % 36 + CASE WHEN @Val % 36 < 10 THEN 48 ELSE 55 END) + @Result,
               @Val = FLOOR(@Val/36)
    END
 
    RETURN @Result
END
GO
--------------------- Uso --------------------
select dbo.fn_FromBase10To36(2061) --Restituirà: '001L9'

Templates

Script in transazione

Esempio di come costruire uno script che, usando una transazione,

-- DEVELOPER NAME – REFERENCE GAP/BUG 
 
SET XACT_ABORT ON;
 
BEGIN TRY
    BEGIN TRANSACTION;
 
    -- Code goes here
 
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0
        ROLLBACK TRANSACTION;
 
    DECLARE
        @ERROR_SEVERITY INT,
        @ERROR_STATE    INT,
        @ERROR_NUMBER   INT,
        @ERROR_LINE     INT,
        @ERROR_MESSAGE  NVARCHAR(4000);
 
    SELECT
        @ERROR_SEVERITY = ERROR_SEVERITY(),
        @ERROR_STATE    = ERROR_STATE(),
        @ERROR_NUMBER   = ERROR_NUMBER(),
        @ERROR_LINE     = ERROR_LINE(),
        @ERROR_MESSAGE  = ERROR_MESSAGE();
 
    RAISERROR('Msg %d, Line %d, :%s',
        @ERROR_SEVERITY,
        @ERROR_STATE,
        @ERROR_NUMBER,
        @ERROR_LINE,
        @ERROR_MESSAGE);
	/* ATTENZIONE l'esecuzione comunque continuerà sino alla fine */
END CATCH

Relazioni e Constraint

Gerarchia relazioni

Assegna un livello più basso alle tabelle che hanno meno relazioni esterne, sono le tabelle di lookup ovvero quelle che son più referenziate dalle altre

   WITH FK_TABLES AS (
    SELECT    S1.NAME AS FROM_SCHEMA    
    ,        O1.NAME AS FROM_TABLE    
    ,        S2.NAME AS TO_SCHEMA    
    ,        O2.NAME AS TO_TABLE    
    FROM    SYS.FOREIGN_KEYS FK    
    INNER    JOIN SYS.OBJECTS O1    
    ON        FK.PARENT_OBJECT_ID = O1.OBJECT_ID    
    INNER    JOIN SYS.SCHEMAS S1    
    ON        O1.SCHEMA_ID = S1.SCHEMA_ID    
    INNER    JOIN SYS.OBJECTS O2    
    ON        FK.REFERENCED_OBJECT_ID = O2.OBJECT_ID    
    INNER    JOIN SYS.SCHEMAS S2    
    ON        O2.SCHEMA_ID = S2.SCHEMA_ID    
    /*FOR THE PURPOSES OF FINDING DEPENDENCY HIERARCHY       
        WE'RE NOT WORRIED ABOUT SELF-REFERENCING TABLES*/
    WHERE    NOT    (    S1.NAME = S2.NAME                 
            AND        O1.NAME = O2.NAME)
)
,ORDERED_TABLES AS 
(        SELECT    S.NAME AS SCHEMANAME
        ,        T.NAME AS TABLENAME
        ,        0 AS LEVEL    
        FROM    (    SELECT    *                
                    FROM    SYS.TABLES                 
                    WHERE    NAME <> 'SYSDIAGRAMS') T    
        INNER    JOIN SYS.SCHEMAS S    
        ON        T.SCHEMA_ID = S.SCHEMA_ID    
        LEFT    OUTER JOIN FK_TABLES FK    
        ON        S.NAME = FK.FROM_SCHEMA    
        AND        T.NAME = FK.FROM_TABLE    
        WHERE    FK.FROM_SCHEMA IS NULL
        UNION    ALL
        SELECT    FK.FROM_SCHEMA
        ,        FK.FROM_TABLE
        ,        OT.LEVEL + 1    
        FROM    FK_TABLES FK    
        INNER    JOIN ORDERED_TABLES OT    
        ON        FK.TO_SCHEMA = OT.SCHEMANAME    
        AND        FK.TO_TABLE = OT.TABLENAME
)SELECT    DISTINCT    OT.SCHEMANAME
,        OT.TABLENAME
,        OT.LEVEL
FROM    ORDERED_TABLES OT
INNER    JOIN (
        SELECT    SCHEMANAME
        ,        TABLENAME
        ,        MAX(LEVEL) MAXLEVEL        
        FROM    ORDERED_TABLES        
        GROUP    BY SCHEMANAME,TABLENAME
        ) MX
ON        OT.SCHEMANAME = MX.SCHEMANAME
AND        OT.TABLENAME = MX.TABLENAME
AND        MX.MAXLEVEL = OT.LEVEL
 AND  OT.TABLENAME LIKE '%[_]S[_]%'
 or OT.TABLENAME LIKE 'SY%'
 ORDER BY OT.LEVEL DESC , OT.TABLENAME

Constraint Toglierli

Per singola tabella

ALTER TABLE tableName NOCHECK CONSTRAINT ALL

Per TUTTE le tabelle in automatico

EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'

Constraint Ristabilirli

Per singola tabella

ALTER TABLE tableName WITH CHECK CHECK CONSTRAINT ALL

Per TUTTE le tabelle in automatico

EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all'

Per tutte le tabelle senza interruzione al primo errore:


Progressivo per Identity

Come resettare l'Identity seed? Trattasi spesso di campo identità chiave primaria con autoincremento.

DBCC CHECKIDENT ('[TestTable]', RESEED, 0);
GO

Operazioni Massive

Bulk Insert

(riportato da altra sezione non manutenibile)
bulkinsert
Attenzione a che SQL SERVER abbia i diritti necessari nella cartella in cui si accede e che possa vederla.
Attenzione nel caso ci siano colonne campi con identity (es la prima colonna) occorre prevedere anche il contenuto per quel campo ovviamente lasciandolo vuoto. Es. file CSV da importare

CAMPO_1,CAMPO_2,CAMPO_3
1,393403939199,390110682865
2,393487017598,3905711605793
3,393404554674,3905221403508
4,393402640286,390249787047
5,393453396121,3908281840785
6,393421639555,390445526150
7,393408589408,
8,393458389120,39078466315 
9,393421424335,390875872441
10,393421437504,390957695669
11,393426631023,3909321942107
12,393452210188,3903451821441
BULK INSERT TmpStList FROM 'c:\TxtFile1.txt' WITH (FIELDTERMINATOR = ',')

Altro esempio:

BULK INSERT [VF_MSIDN_GN] 
FROM 'D:\Test\TxtFile1.txt'
WITH  (FIRSTROW=2,			--Per scartare l'intestazione CHE è AL RIGO\RECORD 1
	  FIELDTERMINATOR=',',
	  ROWTERMINATOR='\n');

Soluzione sul terminatore

Da mssqltips.com Tenuto conto che senza alcuna indicazione il valore predefinito è \n (carattere di nuova riga). Potrebbe darsi che non funziona l'identificazione del carattere terminarore di riga, del parametro "ROWTERMINATOR".
Un altro modo per identificarlo è usando il codice esadecimale del carattere:
(LF) = '0x0a' Ad es. per files importati da UNIX
(CR) = '0x0d' Ad es. per files importati da MAC
Quindi nel caso si importi un file da UNIX si userà:

BULK INSERT [VF_MSIDN_GN] 
FROM 'D:\Da Linux.txt'
WITH  (FIRSTROW=1,		--Per scartare l'intestazione
	  FIELDTERMINATOR = ',',
	  ROWTERMINATOR = '0x0a'--Equivalente di   \n   ovvero (LF) = Line Feed
	  );

TABELLA terminatori con codifica esadecimale:

Shortcut   Codice Esadecimale    Codice mnemonico     Descrizione
\n         0x0a                  LF                   Line feed        = nuova linea
\r         0x0d                  CR                   Carriage return  = ritorno accapo

Bulk insert dinamica

DECLARE @PathToCheck	VARCHAR(512) = 'D:\Documenti\DOC Files\Vodafone\_Attivita\Migrazione TTU Premium PIN ver 2.0',
		@FileName		VARCHAR(256) = 'Segrate-dati_Landolfi-Recorder.txt',
		@PathFull		VARCHAR(512),		
		@SQLCommand		AS NVARCHAR(MAX),
		@TableName		AS NVARCHAR(50) = '[LANDOLFI_RECORDER]'
 
SET @PathFull = @PathToCheck + '\' + @FileName
 
SET @SQLCommand = 'BULK INSERT [MVNOTeleTu].[dbo].' + @TableName + '
FROM ''' + @PathFull + ''' 
WITH  (FIRSTROW=2,			--Per scartare intestazione
	  FIELDTERMINATOR='',''); 
'
Print 'Exec: 
' + @SQLCommand
 
EXECUTE sp_executesql @SQLCommand

Utility BCP

Link interno: BCP

Backup \ Restore

Backup

 

Restore

Anziché usare SSMS da script si può:

--Imposta il Database a "single user Mode"
ALTER DATABASE [RS_Control_VNO]
SET SINGLE_USER WITH
ROLLBACK IMMEDIATE
 
--Ripristino:
RESTORE DATABASE [RS_Control_VNO]
FROM DISK = 'D:\SQL_DB_Backup\RS_Control_backup_2019_09_12_181215_5991987.bak'
WITH MOVE 'RS_Control_VNO'		TO 'D:\SQL_DB_Data\RS_Control_VNO.mdf',		--MDF LogicalName
	 MOVE 'RS_Control_VNO_log'	TO 'D:\SQL_DB_Log\RS_Control_VNO_log.ldf'	--LDF LogicalName
 
/*
Se non si verificano errori nello statement precedente il database sarà ora in modalità multiuser.
Se si verifica un errore andrà comunque eseguito il seguente comando per ripristinare la modalità 
multiutente.*/
ALTER DATABASE [RS_Control_VNO] SET MULTI_USER

Che nome dare a MDF e LDF logical name:

SSMS DB Restore statement info.png

Esecuzione SSIS packages

Esempi su come usare istruzioni Transact-SQL per eseguire un pacchetto SSIS archiviato nel catalogo SSIS.
Materiale:

Il seguente script E' in modo ASINCRONO!

DECLARE @execution_id	AS bigint,
		@var0	AS smallint = 1
 
EXEC [SSISDB].[catalog].[create_execution]		--SP che prepara l'esecuzione ma non lancia il SSIS
			@package_name	= N'SP_ES_Project Import.dtsx', 
			@execution_id	= @execution_id OUTPUT, 
			@folder_name	= N'CC_CV', 
			@project_name	= N'Project ES', 
			@use32bitruntime= True, -- Caso esecuzione con Driver a 32 bit !!!
			@reference_id	= Null, 
			@useanyworker	= True, 
			@runinscaleout	= False--True !!!!!!!!!!!!!!!!
SELECT @execution_id
EXEC [SSISDB].[catalog].[set_execution_parameter_value]
					@execution_id,  
					@object_type	= 50, 
					@parameter_name	= N'LOGGING_LEVEL', --Usare "SYNCHRONIZED'" x esecuzione SINCRONA!
					@parameter_value= @var0
EXEC [SSISDB].[catalog].[start_execution]	--SP che da il via alla esecuzione del SSIS 
					@execution_id,  
					@retry_count=0
GO
--ATTENZIONE attendere qualche secondo per avere il risultato perché è una esecuzione NON SINCORNA!
--Dà comunque esito positivo a prescindere se il SSIS fallisce!!!

Purtroppo per verificare se l'esecuzione è realmente andata a buon fine aggiungere sotto il seguente script

-- Check package status, and fail script if the package failed
IF 7 <> (SELECT [status] 
         FROM [SSISDB].[catalog].[executions] 
         WHERE execution_id = @execution_id)
    RAISERROR('Esecuzione del SSIS fallita.', 16, 1)

Lo script di sopra può essere generato automaticamente eseguire i passi indicati qui sotto:

Script Esecuzione SSIS 01.png

Soluzione problemi

Resettare campo password in una tabella

Capita di dover resettare un campo password di un record in tabella con una di default conosciuta. Il problema è nel fatto che il campo password è crittografato quindi non si può nè copiare ed incollare semplicemente e nè decodificare quindi si può copiare la password usata in un record per impostare quella di un altra, ecco la tecnica

-- Per prova metto a confronto in un unico rigo la password del record da cambiare
-- con quella del record da usare come copia template
SELECT 
  am_dest.Password P_Dest, 
  am_dest.PasswordSalt P_Dest_salt, 
  am_source.Password P_Source,
  am_source.PasswordSalt P_Source_salt
FROM [FoxCCAccounts].[dbo].[aspnet_Membership] as am_dest,
     [FoxCCAccounts].[dbo].[aspnet_Membership] as am_source
where am_source.UserId = '6D005825-8DE3-4690-B521-E2D5B1F047AC'
	and am_dest.UserId = '4D750AA6-C87A-4FDA-A9A4-C5D66016A251'
 
-- Infine l'update:
UPDATE am_dest
	SET  am_dest.Password = am_source.Password,
		 am_dest.PasswordSalt = am_source.PasswordSalt
FROM [FoxCCAccounts].[dbo].[aspnet_Membership] as am_dest,
     [FoxCCAccounts].[dbo].[aspnet_Membership] as am_source
where am_source.UserId = '6D005825-8DE3-4690-B521-E2D5B1F047AC'
	and am_dest.UserId = '4D750AA6-C87A-4FDA-A9A4-C5D66016A251'

Esecuzione di una store con parametri funzioni

Se si vuol eseguire una store procedure da Management studio passando, ad es, in alcuni parametri la data odierna con la funzione GetDate() occorrerà eludere il problema come segue, usando la valorizzazione esterna dei parametri.

EXEC	[dbo].[p_CU_B_ACC_TRACK_EXT_NZL_Insert]
		@COMPANY_CODE = '071',
		@DIVISION_CODE = '001',
		@CUSTOMER_CODE = '075900MP',
		@DT_CLAIM_LODGED = @data,
		@DT_QUESTIONNAIR_COMPLETE = @data,
		@DT_ENT_APPOINTMENT_SCHEDULED = @data,
		@DT_AUDIOGRAM_SENT = @data,
		@DT_ENT_APPOINTMENT = @data,
		@DT_NEXT_RECALL = @data,
		@FLG_FUNDING_APPROVED = '0',
		@FLG_FUNDING_COMPETITOR = '0',
		@FLG_FUNDING_DECLINED = '0',
		@FLG_NOT_MOTIVATED = '0',
		@FLG_NOT_CONTACT = '0',
		@FLG_NOT_COMPETITOR = '0',
		@FLG_ACC_NEW = '0',
		@FLG_ACC_REAID = '0',
		@USERINSERT = 'SPXMIW2869\giuseppe.aino',
		@ROWGUID = '00000000-0000-0000-0000-000000000000'

Correzione di errori

Autenticazione

Se da una una applicazione WEB .Net non si riesce ad accedere al DB, usando l'autenticazione integrata di Windows, a causa del seguente errore:

Login failed for user 'IIS APPPOOL\DefaultAppPool'

Ciò è dovuto al fatto che l'utente IIS non ha diritti per acedere al DB neanche in sola lettura. Il seguente script, da lanciare sul DB Master, crea una nuova Login e nuovo utente da associare all'aplication Pool, ATTENZIONE che dopo averlo fatto occorrerà finalmente associare i diritti\ruoli che si vogliono all'utente sul DB su cui si vuol lavorare.

IF NOT EXISTS (SELECT name FROM sys.server_principals WHERE name = 'IIS APPPOOL\DefaultAppPool')
BEGIN
    CREATE LOGIN [IIS APPPOOL\DefaultAppPool] 
      FROM WINDOWS WITH DEFAULT_DATABASE=[master], 
      DEFAULT_LANGUAGE=[us_english]
END
GO
CREATE USER [WebDatabaseUser] 
  FOR LOGIN [IIS APPPOOL\DefaultAppPool]
GO
EXEC sp_addrolemember 'db_owner', 'WebDatabaseUser'
GO

Funzionali

Nr chiamate contemporanee

Sulla tabella [ag_cdr] son memorizzati i records relativi alle chiamate telefoniche, ogni chiamata inizia all'istante memorizzato nel campo adetdate.
Si vuole determinare il numero di chiamate intervenute nell'arco di 10" restringendo la selezione in un intervallo temporale.

SELECT 
	--adetdate, 
	LEFT(CONVERT(VARCHAR, adetdate, 120), 18),
	COUNT(*)  AS TotChiamate 
FROM [ag_cdr]
WHERE adetdate BETWEEN '2018-06-01 00:00:00.000' 
	AND '2018-06-30 23:59:59.999' 
GROUP BY LEFT(CONVERT(VARCHAR, adetdate, 120), 18)
ORDER BY TotChiamate DESC

In pratica si raggruppano tutti i records che hanno data trasformata in stringa in cui si son tolte le unità decimali dei secondi. La LEFT estrae una sottostringa di n caratteri (18 nel nostro caso) a partire dalla sinistra. 120 è il codice di conversione per ottenere una stringa nel formato: yyyy-mm-dd hh:mm:ss

Mappa e Link


MS SQL



Parole chiave:

Author