Datenbank shrinken, aber die Dateien werden nicht kleiner?

Prinzipiell sollte es möglich sein eine Datenbank oder einzelne Dateien, z.B. das LOG zu verkleinern. Aber diese werden niemals kleiner, als die „Inital Size“.

Wenn es jedoch immer noch nicht funktioniert, kann es an vorhandenen Indizes liegen, die auch sehr stark fragmentiert sein können.

Gute „vorbereitete Lösung“ habe ich gefunden bei:

https://blog.pmd-media.com/2009/10/08/howto-verkleinern-einer-microsoft-sql-server-datenbank/

--Erst alle Indizes neu aufbauen
DECLARE @TableName varchar(255)
DECLARE TableCursor CURSOR FOR
   SELECT DISTINCT QUOTENAME(TABLE_SCHEMA)+'.'+QUOTENAME(table_name)
   FROM information_schema.tables
   WHERE table_type = 'base table'
   order by 1 asc
OPEN TableCursor
FETCH NEXT FROM TableCursor INTO @TableName
WHILE @@FETCH_STATUS = 0
BEGIN
   print @TableName+'....'
   DBCC DBREINDEX(@TableName,' ',90)
   FETCH NEXT FROM TableCursor INTO @TableName
END
CLOSE TableCursor
DEALLOCATE TableCursor
print 'FERTIG'

--Und nachher wirklich shrinken:
go
dbcc shrinkdatabase    (0, 10, NOTRUNCATE)
--Erster Parameter := Aktuelle DB
--Zweiter Parameter := Wieviel Prozent soll "leer" bleiben
go
dbcc shrinkdatabase    (0, 10, TRUNCATEONLY)
--dto.
GO

/*
--Quelle: https://qastack.com.de/server/31554/how-to-check-progress-of-dbcc-shrinkfile
--In einem anderem Fenster könnte man sehen wie weit der Shrink-Prozess ist:
select  T.text, R.Status, R.Command, DatabaseName = db_name(R.database_id)
        , R.cpu_time, R.total_elapsed_time, R.percent_complete as [ca.percent]
from    sys.dm_exec_requests R
        cross apply sys.dm_exec_sql_text(R.sql_handle) T
*/

Dynamisches SQL – Beispiel „Anzahl von Sätzen allen Tabellen“

Gelegentlich möchte man sich T-SQL generieren lassen und dann auch noch starten zu lassen. Als Beispiel ist eine Kontrolle, ob wirklich alle Tabellen „truncated“ wurde…. Manchmal kommt noch eine Tabelle hinzu und schon wird vergessen dass auch diese neue Tabelle auch geleert sein sollte. Das Beispiel soll nur zeigen, wie es möglich ist – der Befehl STRING_AGG funktioniert erst ab SQL Server 2016 (Vorher wurde XML in dem SQL eingebaut):

DECLARE @Schema nvarchar(64) = 'dbo'
DECLARE @SQL nvarchar(max)
DECLARE @ParmDefinition nvarchar(max) = '@CountOUT int OUTPUT'
DECLARE @Count bigint
Select @SQL='SELECT @CountOUT = '+STRING_AGG('(Select count(1) from ['+[schemas].[name]+'].['+[tables].[name]+'])','+')
from sys.tables tables left outer join sys.schemas schemas on schemas.schema_id=tables.schema_id 
where [tables].[type]='U' 
and [schemas].[name] like @Schema
EXEC sp_executesql @SQL, @ParmDefinition, @CountOUT=@Count OUT
Select @Count as TotalRows

Hinweis: Der Befehlt STRING_AGG() darf jedoch maximal 8000 Zeichen produzieren – daher wird dies im Zweifel nicht benutzt werden kann!

Link/s:
https://docs.microsoft.com/de-de/sql/relational-databases/system-stored-procedures/sp-executesql-transact-sql?view=sql-server-2017

T-SQL Settings: LANGUAGE, Dateformat und DATEFIRST

Immer wieder wäre es schön kurzeitig andere Einstellungen zu nutzten. Speziell damit T-SQL Batches sehr unabhängig arbeiten können:

--Save the old / usual settings:
DECLARE @DATEFIRST int = @@DATEFIRST
DECLARE @LANGUAGE nvarchar(100) = @@LANGUAGE
DECLARE @DATEFORMAT nvarchar(100) = (
   select	s.date_format 
   from	sys.dm_exec_sessions s 
   where	s.session_id = @@SPID
   )
--Set new temporary Settings:
SET DATEFIRST 7;
SET DATEFORMAT mdy;
SET LANGUAGE US_ENGLISH;
…
…
--Restore the saved settings:
SET LANGUAGE @language;  /*Germany: "Deutsch" */
SET DATEFIRST @DATEFIRST;  /*Germany: "dmy" */
SET DATEFORMAT @DATEFORMAT;  /*Germany: "1" */

ACHTUNG: Variablen sind alle verloren nach jedem „GO“ – auch wenn ein GO in einem Kommentar seht ist das meist verloren!
Wie auch immer, solche Einstellungen gelten ohnehin nur in aktuellen Session.