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

Print Friendly, PDF & Email

BIML

https://www.informatik-aktuell.de/entwicklung/programmiersprachen/biml-macht-datenbeladung-zum-kinderspiel.html

https://www.cathrinewilhelmsen.net/2016/04/21/get-started-bimlexpress/

 

Print Friendly, PDF & Email

SQL: Deploy SSIS-Solution

Es gibt prinzipiell verschiedene Stellen, wohin man den Code ablegen kann, damit der SQL Server diesen aufruft.

  • Filesystem
  • SQL Server
  • SSIS Package Store
  • SSIS Catalog

Wobei ich derzeit diese letzte Variante „SSIS Catalog“ in aktuellen Datenbanken. Es wird in der Datenbank automatisch eine Datenbank „SSISDB“ und soweit die Service Integration auch installiert ist, gibt es auch einen „Integration Services Catalog“. Beim Erstem Aufruf muss ein Passwort hinterlegt werden (IMHO unveränderbar). Es wird dann der erste Ebene „SSISDB“ angelegt und darunter können/müssen für jede SSIS-Solution, die man hier ablegt gleich einen neuen Ordner anlegen. Daher bitte die Ordner die Ordnernamen sprechend festlegen (wieder IMHO kaum unveränderbar).

Hier meine Schritte:

Print Friendly, PDF & Email

SQL: Agent Job anlegen

Das Anlegen von Agent Jobs sind eigentlich recht einfach. Aber gilt nicht für den allerersten Job;-). Aber es sind mehrere Schritte:

  1. Meist erst das Bereitstellen einer SSIS-Solutions. Dazu mehr unter „SQL: Deploy SSIS-Solution“
  2. Einmalig meist das Anlegen eines Credentials und eines Proxy. Dazu mehr unter „SQL: Credentials und Proxy“
  3. Dann das eigentliche Anlegen des Agent Jobs (hier unten im Text)
  4. Und das Testen…Und wo man die Ursachen von Fehlern findet (hier ganz unten im Text)

Möglicherweise fehlen noch Rechte:

Lösung: Rolle ssis_admin in SSISDB und Rolle db_ssisoperator in msdb hinzufügen. Falls dann sind aber diese „User“ zwar in den beiden Datenbank (jeweils unter: Security / Users) sichtbar, aber so mit einem „X“ oder „irgendwie deaktiviert“… Dann müssen diese User auch in der Datenbank hinzugefügt werden – wie im T-SQL Code:
(Bitte die meinuser und meinlogin anpassen – und häufig sind beide gleichen Buchstabenfolge. Speziell bei AD-Usern und AB-Gruppen.)

USE [SSISDB]
GO
CREATE USER [ meinuser ] FOR LOGIN [ meinlogin ] WITH DEFAULT_SCHEMA=[dbo]
GO
EXEC sp_addrolemember @rolename = 'ssis_admin', @membername = 'meinuser';
GO

USE [msdb]
GO
CREATE USER [ meinuser ] FOR LOGIN [ meinlogin ] WITH DEFAULT_SCHEMA=[dbo]
GO
EXEC sp_addrolemember @rolename = 'db_ssisoperator', @membername = 'meinuser';
GO
Print Friendly, PDF & Email

SQL: Transaktionen Try/Catch?

Es gibt tatsächlich zwei völlig unterschiedliche Ansätze….

Ich nutze diese kürzere – vielleicht etwas älter – Variante:

 Begin Transaction
   Begin Try
   /*Insert/Update/…*/
   End Try
   Begin Catch
      IF @@TRANCOUNT > 0  
         ROLLBACK TRANSACTION;  
   End Catch
IF @@TRANCOUNT > 0  
    COMMIT TRANSACTION; 
/*Das Commit ist das "End Transaction"*/

Die zweite Variante benötigt das „XACT_STATE“ und liest sich noch komplizierter und werde ich nur nutzen, wenn ich mit dem o. g. T-SQL Code nicht weiter komme. Aber beschrieben sind beide Wege von Microsoft in dem u. g. Link

Link:

https://docs.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql?view=sql-server-2017

Print Friendly, PDF & Email

SQL Server: Database Mail

Um das Einrichten von Database Mail-Account kann manuell diese Schritte vornehmen:
(Link: http://sqlcache.blogspot.com/2014/11/sql-server-database-mail.html )

Vermutlich ist diese Bestätigung notwendig:

Und nun dem „Profil“ ein Namen geben und einen SMTP-Account hinterlegen:

Und nun sind die Zugriffsdaten des Exchange Server notwendig…
Wir empfehlen dafür einen eigenen Exchange Account und dies mit dem IT-Administratoren abzusprechen – also eigentlich wie ein normaler Anwender.
Z.B. könnte dieser heißen wie „SQLServer“. 
Möglicherweise ist aber bei Ihnen bei allen anderen SQL Servern auch schon Database Mail eingerichtet und der gleiche Account benutzt ist. Dazu meist nur benutzt bei kritischen Fehlern an alle Admins versendet werden. Wir werden jedoch vermutlich regelmäßig mehr versenden als nur bei Fehlern.
Noch einmal: Dieser „Account“ wird nur E-Mail versenden und nie E-Mail „lesen“ – Also falls E-Mails eingehen, werden diese ewig in dem Postfach liegen bleiben.

Port, SSL-Häkchen und E-Mail Server sind den Adminstratoren bekannt
(„Reply e-mail“ bitte genauso eintragen, wie die „E-mail address“)
Links Information über E-Mail Server:
https://support.office.com/de-de/article/server-einstellungen-die-sie-von-ihrem-e-mail-anbieter-benötigen-c82de912-adcc-4787-8283-45a1161f3cc3

Nach dem „OK“ sind wir wieder zurück:

Und müssen „Next“ klicken und in diesem Schritt muss das Profil aktiviert werden…

In diesem nächstem Schritt müssen wir vermutlich die maximale Größe von E-Mails anpassen. Eine „0“ mehr, also 10 MB erlauben:

Dann wird das lediglich noch einmal zusammengefasst und man muss mit „Finish“beenden. Danach sollten alle fünf Aktionen mit „Success“ beendet sein.

Und der Versand von E-Mails kann jetzt getestet werden:

Falls die Test-Email nicht am Ziel angekommen ist, finden Sie den dort wo die „Send Test E-Mail…“ Popup war, auch das „View Database Mail Log“…

Typische Fehlerldung: „The SMTP Server Requires a Secure Connection or the Client was not Authenticated“
https://blog.sqlauthority.com/2018/06/30/sql-server-database-mail-error-the-smtp-server-requires-a-secure-connection-or-the-client-was-not-authenticated-the-server-response-sas-5-5-1/

Links:
Leider hilft die spezielle SQL Server 2017 – Site gar nicht:
https://docs.microsoft.com/de-de/sql/relational-databases/database-mail/configure-database-mail?view=sql-server-2017

Links:
https://docs.microsoft.com/de-de/sql/relational-databases/system-stored-procedures/sp-send-dbmail-transact-sql?view=sql-server-2017

 

Fehlermeldungen:

Msg 22050, Level 16, State 1, Line 3
Failed to initialize sqlcmd library with error number -2147467259.

Hinweis: Die gleiche Fehlermeldung bekommt man auch, wenn das „QuerySQL“ nicht mit einer vollständigen „Select * FROM Datenbank.Schema.Tabelle“ Formalimus arbeitet. Diese Stored Procedure ruft die „QuerySQL“ in einer neuer Query Umgebung (IMHO: in Master)… Und die Fehlermeldung halte ich als irreführend!

 

Print Friendly, PDF & Email

Indizes aktualisieren….

/**************************************************************
 Bitte als SYSDBA anmelden.

 DEFRAGMENTATION von Indizes - es ist nicht notwendig zusätzliche
 Bibliotheken aufzurufen

 ACHTUNG: HIER SIND ZWEI STELLEN FREIZUSCHALTEN!!!

 HINWEIS: die richtige DB festlegen
   
***************************************************************/
use   --FranksDB
go
--Hier ist bewusst ein Fehler eingebaut, damit die DB korrekt festgelegt ist


--DEFRAGMENTATION:
SET NOCOUNT ON;
DECLARE @objectid int;
DECLARE @indexid int;
DECLARE @partitioncount bigint;
DECLARE @schemaname sysname;
DECLARE @objectname sysname;
DECLARE @indexname sysname;
DECLARE @partitionnum bigint;
DECLARE @partitions bigint;
DECLARE @frag float;
DECLARE @command varchar(8000);
-- ensure the temporary table does not exist
IF EXISTS (SELECT name FROM sys.objects WHERE name = 'work_to_do')
	DROP TABLE work_to_do;

--diesen parameter "DB_ID()" darf man nicht benutzten - wieso auch immmer
DECLARE @DBID bigint;
select @DBID=DB_ID();

-- conditionally select from the function, converting object and index IDs to names.
SELECT	object_id AS objectid,
	index_id AS indexid,
	partition_number AS partitionnum,
	avg_fragmentation_in_percent AS frag
INTO work_to_do
FROM sys.dm_db_index_physical_stats (@DBID, NULL, NULL , NULL, 'LIMITED')
WHERE avg_fragmentation_in_percent > 10.0 AND index_id > 0;
-- Declare the cursor for the list of partitions to be processed.
DECLARE partitions CURSOR FOR SELECT * FROM work_to_do;

-- Open the cursor.
OPEN partitions;

-- Loop through the partitions.
FETCH NEXT
	FROM partitions
	INTO @objectid, @indexid, @partitionnum, @frag;

WHILE @@FETCH_STATUS = 0
	BEGIN;
	SELECT @objectname = o.name, @schemaname = s.name
	FROM sys.objects AS o
	JOIN sys.schemas as s ON s.schema_id = o.schema_id
	WHERE o.object_id = @objectid;

	SELECT @indexname = name FROM sys.indexes WHERE object_id = @objectid AND index_id = @indexid;

	SELECT @partitioncount = count (*) FROM sys.partitions  WHERE object_id = @objectid AND index_id = @indexid;

	-- 30 is an arbitrary decision point at which to switch between reorganizing and rebuilding
	IF @frag <= 10.0
	BEGIN;
		SELECT @command = 'Index: [' + @indexname + '] ON [' + @schemaname + '].[' + @objectname + ']...OK';
	END;

	IF @frag > 10.0 AND @frag <= 30.0
	BEGIN;
		SELECT @command = 'ALTER INDEX [' + @indexname + '] ON [' + @schemaname + '].[' + @objectname + '] REORGANIZE';
		IF @partitioncount > 1
			SELECT @command = @command + ' PARTITION=' + CONVERT (CHAR, @partitionnum);
		--EXEC (@command);  -----HIER FREISCHALTEN!!!!!
	END;

	IF @frag > 30.0
	BEGIN;
		SELECT @command = 'ALTER INDEX [' + @indexname +'] ON [' + @schemaname + '].[' + @objectname + '] REBUILD';
		IF @partitioncount > 1
			SELECT @command = @command + ' PARTITION=' + CONVERT (CHAR, @partitionnum);
		--EXEC (@command); -----HIER FREISCHALTEN!!!!!
	END;
	PRINT 'Executed ' + @command;

	FETCH NEXT FROM partitions INTO @objectid, @indexid, @partitionnum, @frag;
END;
-- Close and deallocate the cursor.
CLOSE partitions;
DEALLOCATE partitions;

-- drop the temporary table
--Select * from work_to_do
IF EXISTS (SELECT name FROM sys.objects WHERE name = 'work_to_do')
	DROP TABLE work_to_do;

-- FERTIG Meldung
PRINT 'All Indices was reorganized or rebuilded. '
Print Friendly, PDF & Email

Microsoft Access Database Engine 2016 Redistributable

Excel-Dateien in ein MS SQL Server importieren ist war schon eine zeitfressende Nervigkeit mit den unterschiedlichen „Störungen“ (einmal positiv beschrieben)…

Wie auch immer dieser o.g. Fehler gibt’s immer wieder einmal vor…
Die Lösung wird ja eigentlich aus der Fehlermeldung vorgibt – aber 32 oder 64 bit? Oder welche Version soll man nehmen?

Link:https://www.microsoft.com/en-us/download/details.aspx?id=54920

Aber diese Fehler sind fast programmiert:

Falls MS Office bereits installiert ist, dann feststellen ob 32 oder 64 bit installiert ist und dann
muss die Installation „/quiet“ erfolgt…
Vorab: Scheinbar wird vom SQL Import/Export-Assistent nur die 32bit Version erkannt! Also ich benötigte immer nur die 32bit Version!

Zitat (o.g. Link):
If Office 365 is already installed, side by side detection will prevent the installation from proceeding. Instead perform a /quiet install of these components from command line. To do so, download the desired AccessDatabaseEngine.exe or AccessDatabaeEngine_x64.exe to your PC, open an administrative command prompt, and provide the installation path and switch Ex: C:\Files\AccessDatabaseEngine.exe /quiet

Print Friendly, PDF & Email

SQL: Index über ein View? Schemabinding ist die Lösung – aber nicht immer…

Schemabindung ist sehr interessant, weil dann komplexe Views plötzlich schnell aufgerufen werden können. Aber hat auch Voraussetzungen und sogar Nachteile haben. Z.B. sind dann alle Tabellen, die auf den View zugreifen gesperrt , gegen struktureller Änderungen. Das bedeutet, wenn ein neues Feld in die Tabelle soll, muss der/die View/s gelöscht werden und dann wieder angelegt werden. Die alle Indizes, dieser betroffenen View/s müssen dann auch wieder angelegt werden.

Voraussetzungen sind recht komplex und sind in der Quelle reichlich beschrieben. Aber es wird keine Fehlermeldung geben, lediglich kann es sein, dass der „View with schemabinding“ lediglich die Daten nicht persistent speichert.

Aber damit man ganz schnell feststellen kann welche SET-Options im System eingerichtet sind ist in einer „neuen“ SSMS-Query hiermit leicht abfragen:

SELECT 
SESSIONPROPERTY ('NUMERIC_ROUNDABORT')  as "NUMERIC_ROUNDABORT soll 0",
SESSIONPROPERTY ('ANSI_PADDING') as "ANSI_PADDING soll 1", 
SESSIONPROPERTY ('ANSI_WARNINGS') as "ANSI_WARNINGS soll 1", 
SESSIONPROPERTY ('CONCAT_NULL_YIELDS_NULL') as "CONCAT_NULL_YIELDS_NULL soll 1",
SESSIONPROPERTY ('ARITHABORT') as "ARITHABORT soll 1",
SESSIONPROPERTY ('QUOTED_IDENTIFIER') as "QUOTED_IDENTIFIER soll 1" ,
SESSIONPROPERTY ('ANSI_NULLS') "ANSI_NULLS soll 1"

https://docs.microsoft.com/de-de/sql/relational-databases/views/create-indexed-views?view=sql-server-2017

Print Friendly, PDF & Email

SQL: Mehrere Sätze als einzelner String zusammenfassen

Weil die neue STRING_AGG() nicht mehr als 8000 Zeichen akzeptiert, muss man sich weiterhin behelfen:

DECLARE @T TABLE (t uniqueidentifier)
Insert into @T
Select '19324C4B-83AE-E211-83C9-005056B05853'
union all 
Select '99324C4B-83AE-E211-83C9-005056B05800'

--Mehrere Sätze als einzelner String zusammenfassen:
SELECT STUFF(
 				(
				SELECT ','+CAST(t as varchar(38))
				FROM @t
				FOR XML PATH ('')
				)
			,1,1,'')

Print Friendly, PDF & Email

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

Print Friendly, PDF & Email

SQL Server Icons mit blauem Fragezeichen?

Es ist zwar nicht weiter wichtig, aber wenn es irritiert oder konkrete Fragen gestellt wird, habe auch ich gesucht und wurde fündig….

Es ist lediglich der SSMS nicht in der Lage den Status einzelner Dienste des angebundenen fernen SQL Servers

Link 1: https://dba.stackexchange.com/questions/176666/blue-icon-with-question-mark-what-does-it-mean

Hier wird klar der Port 135 des Firewall und es ist von Microsoft mehr Information zu beschaffen:

Link 2: https://docs.microsoft.com/en-us/sql/sql-server/install/configure-the-windows-firewall-to-allow-sql-server-access?view=sql-server-2017#BKMK_port_135

Print Friendly, PDF & Email

SQL Server: Welcher Port wird vom SQL Server genutzt?

Es ist zwar möglich die alle Ports festzustellen
netstat -ano
Aber das macht eine zu lange Liste…
Kurzer Test ob der Standard Port 1433 festgelegt ist:
netstat -ano | findstr 1433
Aber wenn das nichts bringt, dann den SQL Server selber fragen:

SELECT DISTINCT 
    local_tcp_port 
FROM sys.dm_exec_connections 
WHERE local_tcp_port IS NOT NULL 
Print Friendly, PDF & Email

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.

Print Friendly, PDF & Email

Voraussetzung für das Anlegen von SSIS – SQL Agent Jobs

Vorab:
Um einen normalen SSIS-Job (*.dts oder *.ispac) als SQL Server Agent Job laufen zu lassen, muss ein Proxy festgelegt sein – und beim Anlegen eines Proxy werden die hinterlegten Credentials verlangt.
Also muss zuerst ein Credentials hinterlegt werden.

SQL Server Aufruf: „Security / Credentials“
Credentials name: SendDataMigrationStatusCred
Identity: „Domain User“ (e.g. Admin, SSISAdmin… ask the Support)

SQL Server Aufruf: „SQL Server Agent / Proxies“:
Proxy name: SendDataMigrationStatusProxy
Credentials name: SendDataMigrationStatusCred
Active to he following subsystems: SQL Server Integration Services Packages
(Wir wollen üblicherweise diesem Proxy nur das Erlauben, was unbedingt nötig ist – also nur ein einziges Häkchen)

SQL Server Aufruf: „SQL Server Agent / Jobs“
Anlage eines neues Agent Jobs:  DeltaImport
Der Job hat nur einen einzigen Step (in diesem Beispiel):
Hinweis: Dieses Beispiel nutzt einen *.ispac Job, der im SSIS-Catalog hinterlegt ist.

„Schedules“ oder andere Einstellungen können an dieser Stelle festgelegt werden.

Oder es werden die Schedules nicht hier definiert, sondern als „Maintenance Plans“. Das erlaubt mehr Möglichkeiten wie ein „Controlling“. Damit können bei Abbruch eines Agent Jobs andere Agent Jobs aufgerufen werden oder bestimmte Einstellungen zurückgesetzt werden bevor der geplante Agent Job gestartet wird.

 

 

Management / Maintenance Plans
Check DeltaImport“

Print Friendly, PDF & Email

T-SQL: Fehlende Indizes…

Häufig scheinen Abfragen überraschend langsam sein, oder immer langsam werden…. Als Tunings-Maßnahme lohnen sich meist als erster Versuch Indizes in der Datenbank. Lediglich sind bestimmte Rechte für der u. g. TSQL-Code notwendig


-- Missing Index Script
-- Original Author: Pinal Dave (C) 2011
-- verändert von Frank Odenbreit 2011/2013/2016

/*
Es werden zwar die 50 wichtigsten Indizes geholt und diese nachher sortiert nach ihrem Namen
(Ähnlichkeiten sollte man erkennen können, ggf. anpassen bzw. aus kommentieren)
*/


Select *
from (
SELECT TOP 50
	dm_mid.database_id AS DatabaseID,
	dm_migs.user_seeks as user_seeks,
	dm_migs.avg_user_impact as avg_user_impact, 
	dm_migs.avg_user_impact * (dm_migs.user_seeks+dm_migs.user_scans) AS Avg_Estimated_Impact,
	dm_migs.last_user_seek AS Last_User_Seek,	object_name(dm_mid.object_id) AS [TableName],
	--*,

	'CREATE NONCLUSTERED INDEX [ndx' + object_name(dm_mid.object_id) + '__'
	+ REPLACE(REPLACE(REPLACE(ISNULL(dm_mid.equality_columns,''),', ','_'),'[',''),']','') +
	CASE
	WHEN dm_mid.equality_columns IS NOT NULL AND dm_mid.inequality_columns IS NOT NULL THEN '_'
	ELSE ''
	END
	+ REPLACE(REPLACE(REPLACE(ISNULL(dm_mid.inequality_columns,''),', ','_'),'[',''),']','')
	+ ']'
	
	+ ' ON ' + dm_mid.statement		+ ' (' + ISNULL (dm_mid.equality_columns,'')
	+ CASE WHEN dm_mid.equality_columns IS NOT NULL AND dm_mid.inequality_columns IS NOT NULL THEN ',' ELSE
	'' END
	+ ISNULL (dm_mid.inequality_columns, '')
	+ ')'
	
	+ ISNULL (' INCLUDE (' + dm_mid.included_columns + ')', '') 
	+ '  WITH (pad_index=OFF,Fillfactor=90,ignore_dup_key=OFF,allow_row_locks=ON,allow_page_locks=ON,DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]'
	
	AS Create_Statement
	
FROM sys.dm_db_missing_index_groups dm_mig
	INNER JOIN sys.dm_db_missing_index_group_stats dm_migs ON dm_migs.group_handle = dm_mig.index_group_handle
	INNER JOIN sys.dm_db_missing_index_details dm_mid ON dm_mig.index_handle = dm_mid.index_handle
WHERE dm_mid.database_ID = DB_ID()
ORDER BY Avg_Estimated_Impact DESC 
) as t
order by Create_Statement asc
Print Friendly, PDF & Email

SQL Server und VisualStudio: 32 oder 64 bit? Welches Target ist möglich?

Wenn man einen einzigen SQL Server frisch installiert hat, dann scheint es einfach sein. Aber falls man auf eine unbekanntes System kommt, muss man selber schauen:

--SQL Serverversion:
Select @@version

Aber wenn man dann per VisualStudio und/oder den Data Tools Jobs anlegt, dann muss meist das „Target“ korrekt angepasst werden und muss mehr hinterfragen:

<nnn> Version 32/64bit
140 SQL Server 2017
130 SQL Server 2016
120 SQL Server 2014
110 SQL Server 2012

Um 32 bit oder 64 bit zu entscheiden, muss im Filesystem nachgeschaut werden und kontrolliert werden, ob eine DtsDebugHost.exe vorhanden ist:

C:\Program Files (x86)\Microsoft SQL Server\<nnn>\DTS\Binn\

oder

C:\Program Files\Microsoft SQL Server\<nnn>\DTS\Binn\

Print Friendly, PDF & Email

MS Report mit Parameter mit Zeiträume [von – bis]

Bei Anpassungen von Reports sind gelegentlich vorbereitete Zeiträume zielführend und hilfreich:

Select 	
	dateadd(SECOND, -1, [dbo].fn_UTCToLocalTime([dbo].[fn_EndOfToday](getutcdate()))) as EndOfToday
	,[dbo].fn_UTCToLocalTime([dbo].[fn_BeginOfThisWeek](getutcdate())) as BeginOfThisWeek
	, dateadd(SECOND, -1, [dbo].fn_UTCToLocalTime([dbo].[fn_EndOfThisWeek](getutcdate()))) as EndOfThisWeek

	, [dbo].fn_UTCToLocalTime([dbo].[fn_BeginOfLastMonth](getutcdate())) as BeginOfLastMonth
	, [dbo].fn_UTCToLocalTime([dbo].[fn_BeginOfThisMonth](getutcdate())) as BeginOfThisMonth
	, dateadd(SECOND, -1, [dbo].fn_UTCToLocalTime([dbo].[fn_EndOfThisMonth](getutcdate()))) as EndOfThisMonth

	, [dbo].fn_UTCToLocalTime([dbo].[fn_BeginOfLastYear](getutcdate())) as BeginOfLastYear
	, [dbo].fn_UTCToLocalTime([dbo].[fn_BeginOfThisYear](getutcdate())) as BeginOfThisYear
	, dateadd(SECOND, -1, [dbo].fn_UTCToLocalTime([dbo].[fn_EndOfThisYear](getutcdate()))) as EndOfThisYear

Print Friendly, PDF & Email

SQL: Rekursive Abfragen

 


/*
Hierarchie von Firmen
---------------------
Egal wo man steht, erst den obersten ParentAccount suchen 
und von dort aus alle Kinder feststellen
--http://www.bidn.com/blogs/KeithHyer/bidn-blog/2293/hierarchy-with-recursive-cte-and-a-little-borrowed-sorting-trickery
*/


/*Muster MSCRM BusinessUnit:*/
--Select Name, * from Team order by 1

With hBU(Name, BusinessUnitId, ParentBusinessUnitIdName, ParentBusinessUnitId, Levl, sortBU)
As (
	/*Anker*/
	Select Name, BusinessUnitId, ParentBusinessUnitIdName, ParentBusinessUnitId , 0 Levl , CONVERT( VARchar(MAX) , ( BusinessUnit.Name  ) ) as sortBU
	From BusinessUnit 
	Where ParentBusinessUnitId IS NULL /*and Name = 'dkacrm'*/

	union all

	/*Recursion*/
	Select BusinessUnit.Name, BusinessUnit.BusinessUnitId, BusinessUnit.ParentBusinessUnitIdName, BusinessUnit.ParentBusinessUnitId , Levl + 1 as Levl, CONVERT( VARchar(MAX) , ( SortBU + BusinessUnit.Name  ) ) as sortBU
	From BusinessUnit 
		inner join hBU on hBU.BusinessUnitId = BusinessUnit.ParentBusinessUnitId
	Where BusinessUnit.ParentBusinessUnitId IS NOT NULL 

) 
Select coalesce(replicate(char(124)+'    ',Levl-1)+replicate(char(43)+'    ',Levl-Levl+1) ,'') + hBU.Name , *
from hBU
order by sortBU
	



/*Muster MSCRM Account:
  Wobei die Felder CustomerTypeCode und ImportSequenceNumber nur Firmen/Kunden-spezifisch sind
*/
With hAcc(Name, Accountid, ParentAccountIdName, ParentAccountid, CustomerTypeCode, ImportSequenceNumber, Levl, SortAcc)
As (
	/*Anker*/
	Select Name, AccountId, ParentAccountIdName, ParentAccountId, CustomerTypeCode, ImportSequenceNumber, 0 Levl, CONVERT( Varchar(MAX) , Name ) as SortAcc
	From Account 
	Where 1=1
		and CustomerTypeCode in (200002  /*Debitoren*/, 200000  /*Filialen*/)
		and ParentAccountId IS NULL

	union all
	
	/*Recursion in CTE*/
	Select Account.Name, Account.AccountId, Account.ParentAccountIdName, Account.ParentAccountId, Account.CustomerTypeCode, Account.ImportSequenceNumber, Levl + 1, CONVERT( Varchar(MAX) , SortAcc + Account.Name ) as SortAcc
	From Account 
		inner join hAcc on hAcc.Accountid=Account.ParentAccountId
	Where 1=1
		and Account.CustomerTypeCode in (200002  /*Debitoren*/, 200000  /*Filialen*/)
		and Account.ParentAccountId IS NOT NULL
)
Select coalesce(replicate(char(124)+'    ',Levl-1)+replicate(char(43)+'    ',Levl-Levl+1) ,'') + Name as Name, 
	CustomerTypeCode, StringMap.Value as CustomerTypeCodeReadable,
	/*Case when CustomerTypeCode = 200000 then 'Filiale' when CustomerTypeCode = 200002 Then 'Debitor' else '???' end CustomerTypeCodeReadable,*/
	AccountId, ParentAccountId, ParentAccountIdName, CustomerTypeCode, ImportSequenceNumber, Levl
From hAcc
	left outer join StringMap on StringMap.AttributeName = 'CustomerTypeCode' and StringMap.LangId = 1031 and StringMap.AttributeValue = hAcc.CustomerTypeCode
Order by SortAcc








/*Muster SLX Account:*/
Declare @Ankerid char(12);
SET @Ankerid = 'A6UNMA000DQO'; --z.B. Firma Muster GmbH & Co. KG  (ist ein Kind weil es ein Parent hat)
--SET @Ankerid = 'A6UJ9A00050W'; --z.B. Muster Holding AG (ist OberAccount)

--Von hier aus den Obervater finden:
DECLARE @ToplevelAccountid char(12);
WITH hAcc(Account, Accountid, ParentAccountid, Levl)
AS (
	--Anker:	
	Select Account, Accountid, Parentid AccountParentid, 0 Levl 
	from Account 
	where Accountid=@Ankerid
	
	union all
	
	--Rekursion in CTE:
	Select Account.Account Account, Account.Accountid Accountid, Account.Parentid ParentAccountid, Levl + 1
	from Account 
		inner join hAcc on hAcc.ParentAccountid = Account.Accountid
	--where Parentid IS NOT NULL
)
--Select Account, Accountid, ParentAccountid, Levl from hAcc where ParentAccountid IS NULL
Select @ToplevelAccountid = Accountid from hAcc where ParentAccountid IS NULL; 
--Print @ToplevelAccountid

--Von hier aus alle Kinder:
WITH hAcc(Account, Accountid, ParentAccount, ParentAccountid, Levl, SortAcc)
AS (
	--Anker (also alle Sätze, die keine Kinder mehr haben):	
	Select Account, Accountid, cast(NULL AS Varchar(128)) ParentAccount, Parentid ParentAccountid, 0 Levl
	,CONVERT( VARchar(MAX) , Account ) as SortAcc
	from Account 
	where Parentid IS NULL
	and Accountid=@ToplevelAccountid
	
	union all
	
	--Rekursion in CTE:
	Select Account.Account Account, Account.Accountid Accountid, hAcc.Account ParentAccount, Account.Parentid ParentAccountid,	Levl + 1
	, CONVERT( VARchar(MAX) , ( SortAcc + Account.Account  ) ) as SortAcc
	from Account 
		inner join hAcc on hAcc.Accountid=Account.Parentid
	where Parentid IS NOT NULL
)
Select 
Account Account,
coalesce(replicate(char(124)+'    ',Levl-1)+replicate(char(43)+'    ',Levl-Levl+1) ,'') Leveling, 
'' FirstChar, 
Accountid, ParentAccount, ParentAccountid, Levl, 
(Case when @Ankerid = Accountid Then 1 else 0 end) Markierung
,SortAcc
--,Row_Number() Over(order by SortAcc asc) RowNum 
from hAcc 
order by SortAcc 


/*
--Beispiel:
Select parentid, Account, Accountid from Account where Accountid='A6UJ9A000F01'
Select parentid, Account, Accountid from Account where Accountid='A6UJ9A00050W'
*/

Select * from account
Select * from gc_account_ext
Select * from ACC_CORPORATE

Select a.ACCOUNT, a.ACCOUNTID, ac.ACCOUNTID, ac.ACC_PARENTID 
from account a
inner join ACC_CORPORATE ac on a.ACCOUNTID=ac.ACCOUNTID
	

;WITH LoopIT( PARENT, CHILD )
AS (
	--Anker (also alle Sätze, die keine Kinder mehr haben):	
	Select ac.ACC_PARENTID, ac.ACCOUNTID
	From ACC_CORPORATE ac 
	where ac.ACC_PARENTID NOT IN (Select ac2.ACCOUNTID From ACC_CORPORATE ac2) 

	union all
	
	--Rekursion in CTE:
	Select r.ACC_PARENTID, r.ACCOUNTID
	From LoopIT r
		inner join ACC_CORPORATE acr on r.ACCOUNTID = acr.ACC_PARENTID
)
Select PARENT, CHILD FROM LoopIT

Hinweis: Standardmäßig sind jedoch nur 100 Rekursionen erlaubt und werden mit einem Fehler abgerochen. Lösung: Ganz an das Ende des T-SQL Code, also auch hinter „WHERE“-Bedingung/en und „Order BY“:

OPTION (MAXRECURSION 32767)

 

Print Friendly, PDF & Email

Speicher Situation eines SQL Servers


/**************************************************************
Wieviel Platz ist auf dem Filesystem des SQL Servers
und wie wird der RAM benutzt?

***************************************************************/

DECLARE @DB varchar(255)
SET @DB =   --'FOD_Test_DB'
--Hier ist bewusst ein Fehler eingebaut, damit die DB korrekt festgelegt ist



/*
Physikalische Größe und freien Speicher in den Datenbanken
*/
exec ('use '+@DB+';
select 
      name 
    , filename 
    , convert(decimal(12,2),round(a.size/128.000,2)) as FileSizeMB 
    , convert(decimal(12,2),round(fileproperty(a.name,''SpaceUsed'')/128.000,2)) as SpaceUsedMB 
    , convert(decimal(12,2),round((a.size-fileproperty(a.name,''SpaceUsed''))/128.000,2)) as FreeSpaceMB 
from dbo.sysfiles a;'+
'use '+'tempdb'+';
select 
      name 
    , filename 
    , convert(decimal(12,2),round(a.size/128.000,2)) as FileSizeMB 
    , convert(decimal(12,2),round(fileproperty(a.name,''SpaceUsed'')/128.000,2)) as SpaceUsedMB 
    , convert(decimal(12,2),round((a.size-fileproperty(a.name,''SpaceUsed''))/128.000,2)) as FreeSpaceMB 
from dbo.sysfiles a')



/*
Freier Speicher im Filesystem des SQL-Servers: 
*/
exec xp_fixeddrives



/*
Aufteilung des Arbeitspeicher des Systems
*/
/*
Select * from sys.dm_os_memory_pools
Select * from sys.dm_os_memory_allocations
Select * from sys.dm_os_memory_clerks 
Select * from sys.dm_os_memory_objects 
Select * from sys.dm_os_memory_nodes 
--Ab SQL Server 2008 möglich: 
Select cast(round(total_physical_memory_kb/1024.0/1024.0,2) as decimal(10,2)) PhysicalRAM_GB
	,cast(round(available_physical_memory_kb/1024.0/1024.0,2) as decimal(10,2)) AvailableRAM_GB
	,*
from sys.dm_os_sys_memory
*/

Print Friendly, PDF & Email

SQL Server: Strukturelle Änderungen einer Datenbank soll dokumentiert werden…

/*
Jede strukturelle Aenderungen an einer oder allen Datenbanken soll (voellig automatisch) nachvollziehbar sein.

Trigger on a CREATE, ALTER, DROP, GRANT, DENY, REVOKE, or UPDATE STATISTICS statement (DDL Trigger)
Um alle technische Aenderungen nachvollziehen zu koennen.
Also werden alle Veraenderungen an Struktruen von allen Datenbanken dokumentiert.
Dies gilt auch fuer Trigger und neue Datenbanken u.ae.
Es werden somit saemtliche "DDL" Befehle dokumentiert, aber keine DML Befehle und deren Wirkungen!
DDL = Data Definition Language
DML = Data Manipulation Language

Moeglicherweise sollte die getriggerte ƒnderungen 
an die Ziel-Datenbank (bsp. master.dbo.FOD_ddl_log) 
eines zweitem SQL-Server gesendet werden.

Hinweis: sa-Rechte (oder vergleichbare) sind notwendig.
Hinweis: Dieser Trigger ist auf dem SQL-Server unter ServerObjects/Triggers zu finden

Change:
20160126 FOD: Diese Beschreibung und JEGLICHER "DELETE-Code" wurde auskommentiert + with execute as 'sa'


*/


USE master;
GO

--Logging-Tabelle anlegen:
CREATE TABLE FOD_ddl_log (
	id bigint identity(1,1),
       xmlEVENTDATA xml
);
GO

--Logging-View anlegen (nur wg. dem Auslesen von XML):
Create View dbo.vFOD_ddl_log
as
Select id, 
		xmlEVENTDATA.value('(/EVENT_INSTANCE/PostTime)[1]', 'datetime') as PostTime,
		xmlEVENTDATA.value('(/EVENT_INSTANCE/ServerName)[1]', 'varchar(256)') as ServerName,
		xmlEVENTDATA.value('(/EVENT_INSTANCE/DatabaseName)[1]', 'varchar(256)') as DatabaseName, 
		xmlEVENTDATA.value('(/EVENT_INSTANCE/UserName)[1]', 'varchar(256)') as UserName, 
		xmlEVENTDATA.value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(100)') as EventType, 
		xmlEVENTDATA.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(2000)') as TSQLCommand,
		xmlEVENTDATA
from FOD_ddl_log 

--TRIGGER  anlegen:
CREATE TRIGGER FOD_ddl_log 
	/*ON DATABASE*/
	ON ALL SERVER
	WITH EXECUTE AS 'sa'
	FOR DDL_DATABASE_LEVEL_EVENTS 
	AS
	DECLARE @data XML;
	SET @data = EVENTDATA();
	INSERT FOD_ddl_log  ( [xmlEVENTDATA] ) 
	VALUES ( @data ) ;
GO


--- DER CODE SOLL ERST NUR BIS HIER GESTARTET WERDEN!!!


/*
--Test the trigger:
--------------------
Begin Transaction
CREATE TABLE TestTable (a int)
Rollback

CREATE TABLE TestTable (a int)
GO
DROP TABLE TestTable ;
GO
SELECT * FROM master.dbo.vFOD_ddl_log order by PostTime desc;
GO
*/



/*
--ALLES WIEDER ENTFERNEN, WENN ES NICHTGEWUENSCHT IST:
-----------------------------------------------------
--Drop the trigger.
DROP TRIGGER master.dbo.FOD_ddl_log
--ON DATABASE 
ON ALL SERVER
GO
--Drop View vFOD_ddl_log:
use master
go
DROP VIEW dbo.vFOD_ddl_log;
GO
--Drop table FOD_ddl_log:
use master
go
DROP TABLE dbo.FOD_ddl_log;
GO
*/







/*
--Aufwaendiges Logging:
http://www.mssqltips.com/sqlservertip/2085/sql-server-ddl-triggers-to-track-all-database-changes/

--Einfaches Logging:
http://msdn.microsoft.com/en-us/library/ms173781.aspx

--Bedeutung von  ÑEvent_Instanceì
http://www.sqlteam.com/article/using-ddl-triggers-in-sql-server-2005-to-capture-schema-changes


--Die Beschreibung der Events nach Microsoft Technet:
http://technet.microsoft.com/en-us/library/ms186438(SQL.90).aspx
*/


Aufwändiges Logging:
http://www.mssqltips.com/sqlservertip/2085/sql-server-ddl-triggers-to-track-all-database-changes/

Einfaches Logging:
http://msdn.microsoft.com/en-us/library/ms173781.aspx

Bedeutung von „Event_Instance“
http://www.sqlteam.com/article/using-ddl-triggers-in-sql-server-2005-to-capture-schema-changes

Die Beschreibung der Events nach Microsoft Technet:
http://technet.microsoft.com/en-us/library/ms186438(SQL.90).aspx

Print Friendly, PDF & Email

MS SQL: SQL-Code von Views, Trigger Prozeduren und Funktionen darstellen

/*

Darstellen von SQL Code von Views. Trigger, Prozeduren und Funktionen

*/
Select s.name, m.definition 
from sys.sql_modules m inner join sys.views s ON s.object_id = m.object_id 
where 1=1


Select s.name, m.definition 
from sys.sql_modules m inner join sys.triggers s ON s.object_id = m.object_id 
where 1=1


Select s.name, m.definition 
from sys.sql_modules m inner join sys.procedures s ON s.object_id = m.object_id 
where 1=1
order by 1


Select s.name, m.definition 
from sys.sql_modules m inner join sys.objects s on s.object_id = m.object_id and s.Type='FN'
where 1=1
order by 1

Problem 1: Nicht immer sind die CRLF verblieben

Problem 2: Code ist möglw. länger als 4000/8000 Zeichen

Problem 3: Code ist möglw. verschlüsselt

Print Friendly, PDF & Email

MS SQL: Wie weit ist das Datenbank Backup? Wie viele Prozent sind durch?

Falls ein Backup sehr viel Zeit braucht, wäre es schön, wenn man einmal feststellen kann, wie weit das Backup ist:

/*
Wenn ein Backup länger lauft, kann man feststellen wie weit das Backup ist.

Ggf. hilft diese Recht zum Lesen dieses Code auch anderen geben:
GRANT VIEW SERVER STATE TO [sqluser_loginname]
*/

Select Session_id asSPID, r.database_id, r.command, a.text as Query, start_time, percent_complete,
DATEADD(Second, estimated_completion_time/1000, GetDate()) as estimated_completion_time
From sys.dm_exec_requests r cross Apply sys.dm_exec_sql_text(r.sql_handle) a
Where r.command in ('Backup Database', 'Restore Database', 'Backup Log')

Übrigens: Ich habe die Dauer von Backups gebraucht, als Probleme beim Zugriff auf ein RAID System einmal bestand…

Print Friendly, PDF & Email

MS SQL: Wie lange dauert es noch bis die Datenbank wiederhergestellt ist?

Falls die Wiederherstellung einer Datenbank immer noch nicht fertig ist, wäre es schön, wenn man einmal feststellen kann, wie weit die Wiederherstellung zumindest ist…

**** BITTE CODE VORHER LESEN!!!! ****

/*
http://timlaqua.com/2009/09/determining-how-long-a-database-will-be-in-recovery-sql-server-2008/

ACHTUNG: CODE UNTERSCHIEDLICH VOR SQL SERVER 2012: 
	sys.xp_readerrorlog
	sys.sp_readerrorlog

*/


DECLARE @Serverversion integer = 2012  --BITTE CODE VORHER LESEN!!!!
DECLARE @DBName VARCHAR(64) = 'databasename'



If @Serverversion > 2012
BEGIN
	/*
	----------------------------
	SQL Server 2008
	----------------------------
	So, your MSSQL service crashed in the middle of a big transaction? Or you bumped the service while it was rolling back some gigantic schema change (like say a column add on a 800 million row table)? Well, as you prepare your resume in preparation for the fallout from this debockle, you can use the following query to see how much time you have left. Or, I should say, how much time it thinks you have left... which seems to swing wildly up and down... microsoft math ftw.
	*/

	DECLARE @ErrorLog AS TABLE([LogDate] CHAR(24), [ProcessInfo] VARCHAR(64), [TEXT] VARCHAR(MAX))
	INSERT INTO @ErrorLog
	EXEC sys.xp_readerrorlog 0, 1, 'Recovery of database', @DBName
 
	SELECT TOP 5
		 [LogDate]
		,SUBSTRING([TEXT], CHARINDEX(') is ', [TEXT]) + 4,CHARINDEX(' complete (', [TEXT]) - CHARINDEX(') is ', [TEXT]) - 4) AS PercentComplete
		,CAST(SUBSTRING([TEXT], CHARINDEX('approximately', [TEXT]) + 13,CHARINDEX(' seconds remain', [TEXT]) - CHARINDEX('approximately', [TEXT]) - 13) AS FLOAT)/60.0 AS MinutesRemaining
		,CAST(SUBSTRING([TEXT], CHARINDEX('approximately', [TEXT]) + 13,CHARINDEX(' seconds remain', [TEXT]) - CHARINDEX('approximately', [TEXT]) - 13) AS FLOAT)/60.0/60.0 AS HoursRemaining
		,[TEXT]
	FROM @ErrorLog 
	ORDER BY 1 DESC
END
Else
BEGIN
	/*
	----------------------------
	Sql Server 2012 
	----------------------------
	uses a different stored procedure to read the error log:
	*/

	DECLARE @ErrorLog AS TABLE([LogDate] CHAR(24), [ProcessInfo] VARCHAR(64), [TEXT] VARCHAR(MAX))
 	INSERT INTO @ErrorLog
	EXEC master..sp_readerrorlog 0, 1, 'Recovery of database', @DBName
 
	SELECT TOP 5
		 [LogDate]
		,SUBSTRING([TEXT], CHARINDEX(') is ', [TEXT]) + 4,CHARINDEX(' complete (', [TEXT]) - CHARINDEX(') is ', [TEXT]) - 4) AS PercentComplete
		,CAST(SUBSTRING([TEXT], CHARINDEX('approximately', [TEXT]) + 13,CHARINDEX(' seconds remain', [TEXT]) - CHARINDEX('approximately', [TEXT]) - 13) AS FLOAT)/60.0 AS MinutesRemaining
		,CAST(SUBSTRING([TEXT], CHARINDEX('approximately', [TEXT]) + 13,CHARINDEX(' seconds remain', [TEXT]) - CHARINDEX('approximately', [TEXT]) - 13) AS FLOAT)/60.0/60.0 AS HoursRemaining
		,[TEXT]
	FROM @ErrorLog 
	ORDER BY 1 DESC, 2 DESC, 3 DESC
END


Quelle: http://timlaqua.com/2009/09/determining-how-long-a-database-will-be-in-recovery-sql-server-2008/

Print Friendly, PDF & Email

Installation eines SQL SERVER – Error – VS Shell Installation Has Failed with Exit Code 1638

Während einer Installation eines SQL Servers 2016 und/oder SQL Server 2017:

Erste Hinweise: https://blog.sqlauthority.com/2017/12/21/sql-server-fix-error-vs-shell-installation-failed-exit-code-1638/

Workaround / Solution
Die notwendige „Redistributable Version“ installieren. Die gesuchte Version sollte im Installations Log zu finden sein!
Sollte sich diese „Redistributable Version“ jedoch nicht installieren lässt…

…müssen aktuellere Versionen deinstalliert werden, bis dann die verlangte Version installiert werden kann:

Dann die gewünschte Software installieren – in diesem Fall SQL Server 2016 und/oder SQL Server 2017.
Und dann müssen auch alle gerade deinstallierte Versionen wieder installiert werden. Wobei mit den älteren Versionen anfangen!
https://support.microsoft.com/de-de/help/2977003/the-latest-supported-visual-c-downloads

Print Friendly, PDF & Email

Kommaseparierte Liste – Explode (string_split)

Seit SQL Server 2016 gibt es einige neue Funktionen. Ein Beispiel mit dem Code wesentlich kürzer ist die table based function „string_split()“.
Diese Funktion wird als Tabelle aufgerufen und hat nur die Spalte „value“:

/*Test Tabelle und Daten bereitstellen:*/
DECLARE @Test TABLE (id int identity(1,1) NOT NULL, wert nvarchar(MAX) NULL)
INSERT INTO @test VALUES ('a,b,c,d,e,f'), ('1,2,3,4,5,6,7,8,9'), ('aa,bb,cc,dd,ee,ff,gg')
--Select * from @Test 

/*Daten aus einem Feld als Tabelle bereitstellen:*/
Select value 
from @Test 
outer apply string_split(wert,',') 
where id = 3

Print Friendly, PDF & Email

SSIS package executions in „SSISDB“ (Integration Service Catalogs)

Di laufende SSIS package executions in dem Integration Server Catalog finden und ggf. beenden.

Quelle: https://sabigdata.wordpress.com/2015/02/12/stop-ssis-package-execution-in-ssis-catalog/

/*
Stop SSIS package executions in "SSISDB" (Integration Service Catalogs)

Links:
Stop SSIS Package execution in SSIS.Catalog
*/

--per SSMS-Dialog:
--Rechte Maus auf "SSISDB" und "Active Operations" auswählen...Dort den gewünschten Paackage auswählen und auf "STOP" klicken.

--per SQL die "laufende SSIS package executions" bestimmen:
Select status, start_time as start_time2, folder_name, project_name ,* from SSISDB.catalog.executions where end_time is null order by start_time desc
/*
--Die richtige execution_id auswählen und als @operation_id eintragen (typisch MS - muss ja auch keiner Logik folgen):
Exec catalog.stop_operation  @operation_id =  ...
*/

Print Friendly, PDF & Email

SYSTEM_VERSIONING (Temporal Tables)

What is a system-versioned temporal table?
A system-versioned temporal table is a type of user table designed to keep a full history of data changes and allow easy point in time analysis. This type of temporal table is referred to as a system-versioned temporal table because the period of validity for each row is managed by the system

 

 
(Quelle: https://docs.microsoft.com/en-us/sql/relational-databases/tables/temporal-tables)

Beispiel:

SELECT *
FROM Employee
FOR SYSTEM_TIME
BETWEEN '2014-01-01 00:00:00.0000000'
AND '2015-01-01 00:00:00.0000000'

Video: https://channel9.msdn.com/Shows/Data-Exposed/Temporal-in-SQL-Server-2016

Weitere sehr gute Beschreibung: http://sqlhints.com/tag/for-system_time-as-of/

 

Quelle:

http://sqlhints.com/2015/12/31/temporal-tables-in-sql-server-2016-part-2-querying-system-versioned-temporal-table/

 

Print Friendly, PDF & Email