88 messaggi dal 19 ottobre 2012
Ciao a tutti,
spero possiate aiutarmi perchè non so come utilizzare xp_fixeddrives
Nello specific devo inserire in una procedura una cosa del tipo:

se c'è il disco 'N' allora crea la cartella 'Backup' sul disco 'N', altrimenti la crei sul disco 'P'

Grazie in anticipo per le risposte


G.
1.976 messaggi dal 27 luglio 2005
Contributi
salve Eusebio,
queste cose non sono proprio bellissime da fare direttamente in SQL Server... si, lo so, vengono fatte da sempre, hai ragione :)

ad ogni modo, il tutto va fatto utilizzando procedure di sistema NON documentate, con privilegi amministrativi dello user corrente, ed anche con privilegi adeguati a livello di file system per l'account che esegue SQL Server... e solitamente non sempre queste condizioni sono disponibili...
tant'e'....

trivialmente, di seguito un esempio che utilizza xp_fixeddrives per enumerare i dischi disponibili sulla macchina che esegue SQL Server; si provvede di seguito a scartare dischi rimovibili e cd-rom...
per continuare l'esplorazione del file system potremmo quindi utilizzare xp_dirtree opportunamente valorizzato, ma in questo caso possiamo tranquillamente andare oltre, e quindi il secondo batch provvede a verificare la presenza della directory richiesta nella root (o nell'albero) del disco ottenuto... in sua assenza provvediamo alla sua creazione...
SET NOCOUNT ON;
CREATE TABLE #fixdrv ( Name sysname NOT NULL, Size int NOT NULL, iType int NULL, Type sysname NULL );
INSERT #fixdrv (Name, Size) EXECUTE master.dbo.xp_fixeddrives;
UPDATE #fixdrv set Type = 'Fixed', iType = 1 WHERE Type IS NULL;

INSERT #fixdrv (Name, Size) EXECUTE master.dbo.xp_fixeddrives 2;
UPDATE #fixdrv set Type = 'Removable', iType = 4 WHERE Type IS NULL;
INSERT #fixdrv (Name, Size) EXECUTE master.dbo.xp_fixeddrives 3;
UPDATE #fixdrv set Type = 'CD-ROM', iType = 2 WHERE Type IS NULL;
UPDATE #fixdrv set Name = Name + ':\';
SELECT Name AS [Name], CONVERT(decimal(10,3), Size / 1000.0) AS [Size], iType AS [DiskType], Type AS [Type]
  FROM #fixdrv
  ORDER BY Name, iType;
DROP TABLE #fixdrv;

DECLARE @depth int = 1;    -- livello di scansione - 0= tutto il file system
DECLARE @showFiles int = 0; -- 0= non mostrare File - 1= mostra file
EXECUTE master.dbo.xp_dirtree 'C:\', @depth, @showFiles;
GO
--<------- secondo batch che esegue la specifica richiesta
PRINT 'con questi presupposti, possiamo passare come parametro il disco desiderato ed il disco di default;';
DECLARE @DiskRequested varchar(3);
DECLARE @DiskDefault varchar(3);

DECLARE @UseDisk varchar(3);
DECLARE @Folder varchar (50) = 'Backup';
DECLARE @chkdirectory varchar(500) = '';
DECLARE @folder_exists int = 0;
DECLARE @file_results TABLE (
  file_exists int,
    file_is_a_directory int,
    parent_directory_exists int
    );

SELECT @DiskDefault = 'C:\', @DiskRequested = 'D:\';

PRINT 'di nuovo, carichiamo l''albero del file system con i dischi disponibili';
CREATE TABLE #fixdrv ( Name sysname NOT NULL, Size int NOT NULL, iType int NULL, Type sysname NULL );
INSERT #fixdrv (Name, Size) EXECUTE master.dbo.xp_fixeddrives;
UPDATE #fixdrv set Type = 'Fixed', iType = 1 WHERE Type IS NULL;

PRINT 'escludiamo Removibili e CD-ROM';
-- escludi removibili
INSERT #fixdrv (Name, Size) EXECUTE master.dbo.xp_fixeddrives 2;
UPDATE #fixdrv set Type = 'Removable', iType = 4 WHERE Type IS NULL;
-- escludi CD-ROM
INSERT #fixdrv (Name, Size) EXECUTE master.dbo.xp_fixeddrives 3;
UPDATE #fixdrv set Type = 'CD-ROM', iType = 2 WHERE Type IS NULL;
UPDATE #fixdrv set Name = Name + ':\';

PRINT 'con una JOIN tra il set dei dischi disponibili ed il set di disco desiderato e predefinito,';
PRINT 'otteniamo il disco con precedenza maggiore';

WITH ctePreferences AS (
  SELECT @DiskRequested AS [Disk], 0 AS [Precedence]
  UNION
  SELECT @DiskDefault AS [Disk], 1 AS [Precedence]
  ),
cteResult AS (
  SELECT TOP(1) Name AS [Name], CONVERT(decimal(10,3), Size / 1000.0) AS [Size], iType AS [DiskType], Type AS [Type]
    FROM #fixdrv d
    JOIN ctePreferences c ON c.[Disk] = d.[Name]
    WHERE d.iType = 1 -- solo dishi fissi
    ORDER BY c.[Precedence]
  )
  SELECT @UseDisk = c.Name
    FROM cteResult c;

DROP TABLE #fixdrv;


SELECT @UseDisk AS [Disk 2 use];
IF (NOT @UseDisk IS NULL) BEGIN
  PRINT 'il disco esiste, ora verifichiamo che il folder richiesto NON esista';
  SELECT @chkdirectory = @UseDisk + @Folder;
  
  INSERT INTO @file_results 
      (file_exists, file_is_a_directory, parent_directory_exists)
    EXEC master.dbo.xp_fileexist @chkdirectory;
     
    SELECT @folder_exists = file_is_a_directory
    FROM @file_results;

  IF (@folder_exists = 0) BEGIN
    PRINT 'creazione directory';
    EXECUTE master.dbo.xp_create_subdir @chkdirectory;
    END;
  ELSE
    PRINT 'Directory Esistente - nessuna operazione effettuata';
  END;
ELSE
  PRINT 'nessun disco valido';


saluti
Modificato da Andrea Montanari il 20 settembre 2017 14.02 - dimenticavo di aggiungere che, visto trattarsi di extended stored procedures NON documentate, queste potrebbero essere rimosse/modificate/etc in qualsiasi momento e ovviamente non funzionare piu' come desiderato, oltre al fatto che comportano insorgenza della forfora, caduta dei capelli, sgonfiarsi delle gomme della propria automobile, trovare il proprio parcheggio sempre occupato, ...
anche se queste indicazioni sono sempre pubblicate a partire da SQL Server 7.0 ed al momento risultano tutt'ora soddifatte, utilizzare comunque cum grano salis...

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php
88 messaggi dal 19 ottobre 2012
Grazie Andrea,
adesso guardo il tutto.
E se volessi aggiungere al tempdb dei nuovi files mdf in modo dinamico in base alla popsizione del file mdf principale devo usare sempre quanto mi hai inviato? (I tempdb sui server possono essere su dischi diversi)
Grazie mille

G.
1.976 messaggi dal 27 luglio 2005
Contributi
salve,
eusebio1006 ha scritto:
Grazie Andrea,
adesso guardo il tutto.
E se volessi aggiungere al tempdb dei nuovi files mdf in modo dinamico in base alla popsizione del file mdf principale devo usare sempre quanto mi hai inviato? (I tempdb sui server possono essere su dischi diversi)
Grazie mille

G.


i file dati secondari hanno, per uso comune, estensione ".N df"...

in modo dinamico non lo farei mai... in modo dinamico verificando quali parametri? come fai poi a rimuoverli se non sai se siano utilizzati o meno? come li gestisci? no... dinamicamente ed automagicamente non lo farei mai...
questa' e' un'attivita' prettamente amministrativa da fare tramite Management Studio, cosi' non si fanno stupidaggini... metti nel caso degli alert con le funzionalita' di monitor che eventualmente hai, e provvedi manualmente... ma di solito non si fa neanche quello... quest'attivita' normalmente si fa quando si evidenziano dei colli di bottiglia in tempdb, colli di bottiglia non sporadici... ed in base a tali esigenze, si dimensiona lo storage... non dinamicamente :)
si verifica l'uso dei dischi, lo stato dei dischi, i limiti di IO per lettura/scrittura, ... mai dinamicamente...

salutoni

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php
88 messaggi dal 19 ottobre 2012
Ciao Andrea.
Innanzitutto ho aanalizzato quanto hai scritto per il primo punto e trovo utilissimo quanto hai scritto e ora lo adatto per quello che mi serve.
Tornando invece al discorso di ieri purtroppo avendo molte Istanze e dovendo aggiungere dei file mdf al temp db (che come ho scritto possono essere su percorsi diversi) ho necessità di scrivere una query che automaticamente sui Registered Server mi crei questi files in modo massivo.
Quello che ho scritto è questo:

DECLARE @File_Count INT
DECLARE @logical_name SYSNAME
DECLARE @Physical_name VARCHAR
DECLARE @curPhysicalNameVARCHAR(200)
DECLARE @curDirName VARCHAR(200)
DECLARE @Alter_command VARCHAR (MAX)
SET @curDirName = REVERSE(RIGHT(REVERSE(@curPhysicalName),( LEN(@curPhysicalName) - CHARINDEX('\',REVERSE(@curPhysicalName),1)) + 1));
BEGIN
SELECT @Alter_command = 'ALTER DATABASE [TEMPDB] MODIFY FILE (NAME = N''tempdev'', SIZE = 2048576KB , FILEGROWTH = 0)
ALTER DATABASE [TEMPDB] ADD FILE ( NAME = N''tempdev2'' , FILENAME = N''+ @quotename(@curDirName) + ''tempdb2.mdf'''', SIZE = 1048576KB , FILEGROWTH = 0)'
exec @Alter_command
END


ma credo ci sia un prblema con @quotename(@curDirName) che ho dichirato e il nuovo nome file.
Puoi darmi una mano nel risolvere il problema?
Grazie mille
1.976 messaggi dal 27 luglio 2005
Contributi
salve,

ripeto, non lo farei ma in maniera automagica... mai da script al volo... vorrei sempre verificare "il perche'" sia necessario effettuare una cosa simile...

al di la' di cio, ripeto ancora, i file data secondari, solitamente hanno SEMPRE estensione ".Ndf";

Non ho compreso "dove" ti servisse la funzione QUOTENAME(), che tu tra l'altro hai qui riportato sicuramente con un refuso di battitura, ma ad ogni modo la costruzione dinamica del comando richiede che la funzione sia gia' risolta ed aggiunga il risultato alla concatenazione di stringhe...

- come premessa, sposta il contesto di esecuzione del batch al database master, cosi' non dovresti riscontrare problemi di utilizzo (in teoria)...
- altra premessa... personalmente cerco di utilizzare sempre una nomenclatura "standard" e non personale, in quanto si possono riscontrare poi problemi laddove l'istanza di SQL Server utilizzi una collation binaria, e quindi non saresti in grado di fare riscontri tra TEMPDB e tempdb, VARCHAR e varchar, etc...
- qui non hai indicato "come" recuperi il path del file, cosi' ho qui utilizzato sys.master_files...
- ho ridimensionato un po' la capienza delle variabili...

SET NOCOUNT ON;
USE [master];
GO
DECLARE @File_Count int;
DECLARE @logical_name varchar(256);
DECLARE @Physical_name varchar(256);
DECLARE @curPhysicalName varchar(1024);
DECLARE @curDirName varchar(1024);
DECLARE @Alter_command varchar(MAX);

SELECT @curPhysicalName = physical_name 
  FROM sys.master_files f
  WHERE f.name = 'tempdev';

SET @curDirName = REVERSE(RIGHT(REVERSE(@curPhysicalName),( LEN(@curPhysicalName) - CHARINDEX('\',REVERSE(@curPhysicalName),1)) + 1)); 
SELECT @curDirName;

SELECT @Alter_command = 'ALTER DATABASE [tempdb] MODIFY FILE (NAME = N''tempdev'', SIZE = 2048576KB , FILEGROWTH = 0);
ALTER DATABASE [tempdb] ADD FILE ( NAME = N''tempdev2'' , FILENAME = N''' + @curDirName + 'tempdb2.Ndf'', SIZE = 1048576KB , FILEGROWTH = 0);'
--EXEC @Alter_command;

SELECT @Alter_command;
--<----------------------


C:\Program Files\Microsoft SQL Server\MSSQL12.SQLEXPRESS\MSSQL\DATA\


ALTER DATABASE [tempdb] MODIFY FILE (NAME = N'tempdev', SIZE = 2048576KB , FILEGROWTH = 0);
ALTER DATABASE [tempdb] ADD FILE ( NAME = N'tempdev2' , FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.SQLEXPRESS\MSSQL\DATA\tempdb2.Ndf', SIZE = 10485


non ho verificato l'esecuzione dello script, non ho quindi effettivamente eseguito EXEC @Alter_command;
[e non ci provo manco :)]

saluti

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php
1.976 messaggi dal 27 luglio 2005
Contributi
salve,
un paio di informazioni ausiliarie magari utili:
Troubleshooting Insufficient Disk Space in tempdb: https://msdn.microsoft.com/en-us/library/ms176029.aspx
Optimizing tempdb Performance: https://msdn.microsoft.com/en-us/library/ms175527.aspx
Capacity Planning for tempdb: https://msdn.microsoft.com/en-us/library/ms345368.aspx
tempdb Database: https://docs.microsoft.com/en-us/sql/relational-databases/databases/tempdb-database

saluti

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php
88 messaggi dal 19 ottobre 2012
Perfetto Andrea. Grazie.
L'unica cosa è che - oltre ad abilitare l'EXEC @Alter_command - ho messo le parentesi EXEC (@Alter_command). Senza mi dava l'errore
Grazie mille

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.