Verbesserungen bei der Behandlung einiger Datentypen und ungewöhnlicher Vorgänge in SQL Server und Azure SQL-Datenbank
In diesem Artikel wird erläutert, wie beibehaltene Strukturen in Ihrer SQL Server-Datenbank als Teil der Upgradekompatibilitätsstufe überprüft werden können und wie alle betroffenen Strukturen nach dem Upgrade der Kompatibilitätsstufe neu erstellt werden können.
Originalproduktversion: SQL Server 2017, SQL Server 2016
Ursprüngliche KB-Nummer: 4010261
Das Datenbankmodul in Microsoft SQL Server 2016 und Azure SQL-Datenbank umfasst Verbesserungen bei Datentypkonvertierungen und mehreren anderen Vorgängen. Die meisten dieser Verbesserungen bieten eine höhere Genauigkeit, wenn Sie mit Gleitkommatypen und auch mit klassischen Datetime-Typen arbeiten.
Diese Verbesserungen sind alle verfügbar, wenn Sie mindestens 130 Datenbankkompatibilitätsstufe verwenden. Dies bedeutet, dass bei einigen (meist ungewöhnlichen) Ausdrücken verschiedene Ergebnisse für einige Eingabewerte angezeigt werden, nachdem Sie die Datenbank auf Kompatibilitätsebene 130 oder eine höhere Einstellung aktualisiert haben. Diese Ergebnisse können sich in folgenden Ergebnissen widerspiegeln:
- Beibehaltene Strukturen in der Datenbank
- eingeschlossene Tabellendaten, die Einschränkungen unterliegen
CHECK
- Persistente berechnete Spalten
- Indizes, die auf berechnete Spalten verweisen
- gefilterte Indizes und indizierte Ansichten.
Wenn Sie über eine Datenbank verfügen, die in einer früheren Version von SQL Server erstellt wurde, empfehlen wir, nach dem Upgrade auf SQL Server 2016 oder höher zusätzliche Überprüfungen durchzuführen, und bevor Sie die Datenbankkompatibilitätsstufe ändern.
Wenn Sie feststellen, dass eine der dauerhaften Strukturen in Ihrer Datenbank von diesen Änderungen betroffen ist, empfehlen wir, betroffene Strukturen nach dem Upgrade der Datenbankkompatibilitätsstufe neu zu erstellen. Dadurch profitieren Sie von diesen Verbesserungen in SQL Server 2016 oder höher.
In diesem Artikel wird beschrieben, wie beibehaltene Strukturen in Ihrer Datenbank als Teil des Upgrades auf Kompatibilitätsebene 130 oder höher überprüft werden können und wie alle betroffenen Strukturen neu erstellt werden können, nachdem Sie die Kompatibilitätsstufe geändert haben.
Überprüfungsschritte während eines Upgrades auf Datenbankkompatibilitätsstufe
Ab SQL Server 2016 umfassen SQL Server und Azure SQL-Datenbank Verbesserungen an der Genauigkeit der folgenden Vorgänge:
- Ungewöhnliche Datentypkonvertierungen. Dazu gehören folgendes:
- Float/integer to/from datetime/smalldatetime
- Real/float to/from numeric/money/smallmoney
- Float to real
- Einige Fälle von
DATEPART
/DATEDIFF
undDEGREES
CONVERT
die eineNULL
Formatvorlage verwendet
Um diese Verbesserungen für die Ausdrucksauswertung in Ihrer Anwendung zu verwenden, ändern Sie die Kompatibilitätsebene Ihrer Datenbanken in 130 (für SQL Server 2016) oder 140 (für SQL Server 2017 und Azure SQL-Datenbank). Weitere Informationen zu allen Änderungen und einigen Beispielen, die die Änderungen zeigen, finden Sie im Abschnitt "Anhang A ".
Die folgenden Strukturen in der Datenbank können die Ergebnisse eines Ausdrucks beibehalten:
- Tabellendaten, die
CHECK
einschränkungen unterliegen - Gespeicherte berechnete Spalten
- Indizes, die berechnete Spalten im Schlüssel oder enthaltene Spalten verwenden
- Gefilterte Indizes
- Indizierte Sichten
Nehmen Sie das folgende Szenario als Beispiel:
Sie verfügen über eine Datenbank, die von einer früheren Version von SQL Server erstellt wurde oder die bereits in SQL Server 2016 oder einer höheren Version erstellt wurde, jedoch auf Kompatibilitätsebene 120 oder einer früheren Ebene.
Sie verwenden alle Ausdrücke, deren Genauigkeit im Rahmen der Definition beibehaltener Strukturen in Ihrer Datenbank verbessert wurde.
In diesem Szenario haben Sie möglicherweise beibehaltene Strukturen, die von den Verbesserungen der Genauigkeit betroffen sind, die mithilfe der Kompatibilitätsebene 130 oder höher implementiert werden. Wenn dies der Fall ist, empfehlen wir, die dauerhaften Strukturen zu überprüfen und alle betroffenen Strukturen neu zu erstellen.
Wenn Sie betroffene Strukturen haben und sie nach dem Ändern der Kompatibilitätsstufe nicht neu erstellen, können geringfügig andere Abfrageergebnisse auftreten. Die Ergebnisse hängen davon ab, ob ein bestimmter Index, eine berechnete Spalte oder ansicht verwendet wird und ob Daten in einer Tabelle als Verletzung einer Einschränkung angesehen werden könnten.
Notiz
Ablaufverfolgungskennzeichnung 139 in SQL Server
Das globale Ablaufverfolgungskennzeichen 139 wird in SQL Server 2016 CU3 und Service Pack (SP) 1 eingeführt, um die korrekte Konvertierungsemantik im Bereich der DBCC-Überprüfungsbefehle wie DBCC CHECKDB
, DBCC CHECKTABLE
zu erzwingen, und DBCC CHECKCONSTRAINTS
wenn Sie die verbesserte Genauigkeits- und Konvertierungslogik analysieren, die mit Kompatibilitätsebene 130 in einer Datenbank eingeführt wurde, die eine frühere Kompatibilitätsstufe aufweist.
Warnung
Die Ablaufverfolgungskennzeichnung 139 soll nicht kontinuierlich in einer Produktionsumgebung aktiviert werden und sollte nur zum Zweck der Durchführung der in diesem Artikel beschriebenen Datenbanküberprüfungen verwendet werden. Daher sollte sie in dbcc traceoff (139, -1)
derselben Sitzung deaktiviert werden, nachdem die Überprüfungsprüfungen abgeschlossen wurden.
Ablaufverfolgungskennzeichnung 139 wird ab SQL Server 2016 CU3 und SQL Server 2016 SP1 unterstützt.
Führen Sie die folgenden Schritte aus, um die Kompatibilitätsstufe zu aktualisieren:
- Führen Sie eine Überprüfung durch, um alle betroffenen dauerhaften Strukturen zu identifizieren:
- Aktivieren Sie das Ablaufverfolgungskennzeichnung 139 durch Ausführen
DBCC TRACEON(139, -1)
. - Ausführen
DBCC CHECKDB/TABLE
undCHECKCONSTRAINTS
Befehle. - Deaktivieren Sie die Ablaufverfolgungskennzeichnung 139 durch Ausführen
DBCC TRACEOFF(139, -1)
.
- Aktivieren Sie das Ablaufverfolgungskennzeichnung 139 durch Ausführen
- Ändern Sie die Datenbankkompatibilitätsebene auf 130 (für SQL Server 2016) oder 140 (für SQL Server 2017 und Azure SQL-Datenbank).
- Erstellen Sie alle Strukturen neu, die Sie in Schritt 1 identifiziert haben.
Notiz
Ablaufverfolgungskennzeichnungen in Azure SQL-Datenbank Festlegen von Ablaufverfolgungskennzeichnungen werden in Azure SQL-Datenbank nicht unterstützt. Daher müssen Sie die Kompatibilitätsstufe ändern, bevor Sie die Überprüfung durchführen:
- Aktualisieren Sie die Datenbankkompatibilitätsstufe auf 140.
- Überprüfen Sie, ob alle betroffenen dauerhaften Strukturen identifiziert werden.
- Erstellen Sie die Strukturen neu, die Sie in Schritt 2 identifiziert haben.
Anhang A enthält eine detaillierte Liste aller Genauigkeitsverbesserungen und bietet ein Beispiel für jede.
Anhang B enthält einen detaillierten Schritt-für-Schritt-Prozess zur Überprüfung und zum Neuerstellen betroffener Strukturen.
Anhang C und Anhang D enthalten Skripts zum Anheften potenziell betroffener Objekte in der Datenbank. Daher können Sie Ihre Überprüfungen einschränken und entsprechende Skripts generieren, um die Prüfungen auszuführen. Führen Sie das Skript in Anhang D aus, um am einfachsten zu ermitteln, ob beibehaltene Strukturen in Ihren Datenbanken von den Genauigkeitsverbesserungen der Kompatibilitätsebene 130 betroffen sind, um die korrekten Überprüfungen zu generieren, und führen Sie dann dieses Skript aus, um die Überprüfung durchzuführen.
Anhang A: Änderungen der Kompatibilitätsstufe 130
Dieser Anhang enthält detaillierte Listen der Verbesserungen der Ausdrucksauswertung in Kompatibilitätsebene 130. Jede Änderung enthält eine zugeordnete Beispielabfrage. Die Abfragen können verwendet werden, um die Unterschiede zwischen der Ausführung in einer Datenbank anzuzeigen, die eine Kompatibilitätsstufe vor 130 im Vergleich zu einer Datenbank verwendet, die Kompatibilitätsebene 130 verwendet.
In den folgenden Tabellen werden Datentypkonvertierungen und zusätzliche Vorgänge aufgeführt.
Datentypkonvertierungen
Von | An | Change | Beispielabfrage | Ergebnis für Kompatibilitätsebene < 130 | Ergebnis für Kompatibilitätsebene = 130 |
---|---|---|---|---|---|
float , real , numeric , decimal , money oder smallmoney |
datetime oder smalldatetime |
Erhöhen Sie die Rundungsgenauigkeit. Zuvor wurden Tag und Uhrzeit separat konvertiert, und die Ergebnisse wurden abgeschnitten, bevor Sie sie kombiniert haben. | DECLARE @f FLOAT = 1.2 DECLARE @d DATETIME = @f SELECT CAST(@d AS FLOAT) |
1.19999996141975 | 1.2 |
datetime |
bigint, int, or smallint |
Eine negative Datumstime, deren Zeitteil genau ein halber Tag ist oder in einem Tick eines halben Tages falsch gerundet wird (das Ergebnis ist um 1). | DECLARE @h DATETIME = -0.5 SELECT @h, CAST(@h AS INT) |
0 | -1 |
datetime oder smalldatetime |
float, real, numeric, money, or smallmoney |
Verbesserte Genauigkeit für die letzten 8 Bits genauigkeit in einigen Fällen. | DECLARE @p0 DATETIME = '1899-12-31 23:58:00.470' DECLARE @f FLOAT = CONVERT(FLOAT, @p0) SELECT @f, CAST(@f AS VARBINARY(8)) |
-0.00138344907407406, 0xBF56AA9B21D85800 | -0.00138344907407407, 0xBF56AA9B21D8583B |
float |
real |
Grenzprüfungen sind weniger streng. | SELECT CAST (3.40282347000E+038 AS REAL) |
Arithmetischer Überlauf | 3.402823E+38 |
numeric , money und smallmoney |
float |
Wenn die Eingabeskala null ist, gibt es eine rundende Ungenauigkeit, wenn Sie die vier Teile numerischer Elemente kombinieren. | DECLARE @n NUMERIC(38, 0)= 41538374868278625639929991208632320 DECLARE @f FLOAT = CAST(@n AS FLOAT) SELECT CONVERT(BINARY(8), @f) |
0x4720000000000000 | 0x4720000000000001 |
numeric , money und smallmoney |
float |
Wenn die Eingabeskala ungleich Null ist, gibt es eine rundende Ungenauigkeit, wenn Sie durch 10^-Skalierung dividieren. | DECLARE @n NUMERIC(18, 10) = 12345678.0123456781 DECLARE @f FLOAT = CAST(@n AS FLOAT) SELECT CAST(@f AS BINARY(8)) |
0x41678C29C06522C4 | 0x41678C29C06522C3 |
real oder float |
numeric | Verbesserte Rundungsgenauigkeit in einigen Fällen. | DECLARE @f float = 0.14999999999999999 SELECT CAST(@f AS numeric(1, 1)) |
0.2 | 0.1 |
real oder float |
numeric | Verbesserte Genauigkeit, wenn Sie in einigen Fällen auf mehr als 16 Ziffern runden. | DECLARE @v decimal(38, 18) = 1E-18 SELECT @v |
0.000000000000000000 | 0.000000000000000001 |
real oder float |
money oder smallmoney |
Verbesserte Genauigkeit beim Konvertieren großer Zahlen in einigen Fällen. | DECLARE @f float = 2SET @f = POWER(@f, 49) + POWER(@f, -2) SELECT CAST(@f AS money) |
562949953421312.2048 | 562949953421312.25 |
(n)(var)char |
numeric |
Eine Eingabe von mehr als 39 Zeichen löst nicht mehr notwendigerweise einen arithmetischen Überlauf aus. | DECLARE @value nchar(100) = '1.11111111111111111111111111111111111111' SELECT CAST(@value AS decimal(2,1)) |
Arithmetischer Überlauf | 1.1 |
(n)(var)char |
bit |
Unterstützt führende Leerzeichen und Zeichen. | DECLARE @value nvarchar(100) = '1' SELECT CAST(@value AS bit) |
Fehler bei der Konvertierung beim Konvertieren des nvarchar Werts "1" in das Datentypbit. |
1 |
datetime |
time oder datetime2 |
Verbesserte Genauigkeit beim Konvertieren in Datums-/Uhrzeittypen mit höherer Genauigkeit. Beachten Sie, dass Datetime-Werte als Teilstriche gespeichert werden, die 1/300 Sekunden darstellen. Die neueren Uhrzeit- und Datetime2-Typen speichern eine diskrete Anzahl von Ziffern, wobei die Anzahl der Ziffern mit der Genauigkeit übereinstimmt. | DECLARE @value datetime = '1900-01-01 00:00:00.003' SELECT CAST(@value AS time(7)) |
00:00:00.0030000 | 00:00:00.0033333 |
time oder datetime2 |
datetime |
Verbesserte Rundung in einigen Fällen. | DECLARE @value time(4) = '00:00:00.0045' SELECT CAST(@value AS datetime) |
1900-01-01 00:00:00.007 | 1900-01-01 00:00:00.003 |
Vorgang
Vorgang | Change | Beispielabfrage | Ergebnis für Kompatibilitätsebene <130 | Ergebnis für Kompatibilitätsebene 130 |
---|---|---|---|---|
Verwenden Sie die RADIANS DEGREES integrierte Funktion, die den numerischen Datentyp verwendet. |
DEGREES Dividiert durch pi/180, wobei es zuvor mit 180/pi multipliziert wurde. Ähnlich für RADIANS . |
DECLARE @arg1 numeric = 1 SELECT DEGREES(@arg1) |
57.295779513082323000 | 57.295779513082322865 |
Numerische Addition oder Subtraktion, wenn die Skalierung eines Operanden größer als die Skala des Ergebnisses ist. | Das Runden tritt immer nach dem Additions- oder Subtraktionsvorgang auf, während es zuvor manchmal vorkommen konnte. | DECLARE @p1 numeric(38, 2) = -1.15 DECLARE @p2 numeric(38, 1) = 10 SELECT @p1 + @p2 |
8,8 | 8,9 |
CONVERT mit NULL Stil. |
CONVERT mit NULL Formatvorlage wird immer zurückgegeben NULL , wenn der Zieltyp numerisch ist. |
SELECT CONVERT (SMALLINT, '0', NULL); |
0 | NULL |
DATEPART die die Option "Mikrosekunden" oder "Nanosekunden" mit dem Datentyp "datetime" verwendet. |
Der Wert wird nicht mehr auf Millisekundenebene abgeschnitten, bevor er in Mikro- oder Nanosekunden konvertiert wird. | DECLARE @dt DATETIME = '01-01-1900 00:00:00.003'; SELECT DATEPART(MICROSECOND, @dt); |
3000 | 3.333 |
DATEDIFF die die Option "Mikrosekunden" oder "Nanosekunden" mit dem Datentyp "datetime" verwendet. |
Der Wert wird nicht mehr auf Millisekundenebene abgeschnitten, bevor er in Mikro- oder Nanosekunden konvertiert wird. | DECLARE @d1 DATETIME = '1900-01-01 00:00:00.003' DECLARE @d2 DATETIME = '1900-01-01 00:00:00.007' SELECT DATEDIFF(MICROSECOND, @d1, @d2) |
3000 | 3.333 |
Vergleich zwischen Datetime- und Datetime2-Werten mit Nichtzerowerten für Millisekunden. | Der Datetime-Wert wird nicht mehr auf Millisekundenebene abgeschnitten, wenn Sie einen Vergleich mit einem Datetime2-Wert ausführen. Dies bedeutet, dass bestimmte Werte, die zuvor gleich verglichen wurden, nicht mehr gleich vergleichen. | DECLARE @d1 DATETIME = '1900-01-01 00:00:00.003' DECLARE @d2 DATETIME2(3) = @d1 SELECT CAST(@d1 AS datetime2(7)), @d2SELECT CASE WHEN (@d1=@d2) THEN 'equal' ELSE 'unequal' END |
1900-01-01 00:00:00:00.0030000, 1900-01-01 00:00:00.003 gleich | 1900-01-01 00:00:00:00.0033333, 1900-01-01 00:00:00.003 ungleich |
ROUND -Funktion, die den float Datentyp verwendet. |
Rundungsergebnisse unterscheiden sich. | SELECT ROUND(CAST (-0.4175 AS FLOAT), 3) |
-0.418 | -0.417 |
Anhang B: Schritte zum Überprüfen und Aktualisieren beibehaltener Strukturen
Es wird empfohlen, festzustellen, ob die Datenbank über permanente Strukturen verfügt, die von den Änderungen der Kompatibilitätsebene 130 betroffen sind, und dass Sie betroffene Strukturen neu erstellen.
Dies gilt nur für beibehaltene Strukturen, die in der Datenbank in einer älteren Version von SQL Server erstellt wurden, oder mithilfe einer Kompatibilitätsstufe, die niedriger als 130 ist. Die dauerhaften Strukturen, die potenziell betroffen sind, umfassen Folgendes:
- Tabellendaten, die
CHECK
einschränkungen unterliegen - Gespeicherte berechnete Spalten
- Indizes, die berechnete Spalten im Schlüssel oder enthaltene Spalten verwenden
- Gefilterte Indizes
- Indizierte Sichten
Führen Sie in diesem Fall das folgende Verfahren aus.
Schritt 1: Überprüfen der Datenbankkompatibilitätsstufe
- Überprüfen Sie die Kompatibilitätsstufe Ihrer Datenbank mithilfe der Prozedur, die in "Ansicht" dokumentiert ist, oder ändern Sie die Kompatibilitätsebene einer Datenbank.
- Wenn die Kompatibilitätsebene der Datenbank niedriger als 130 ist, empfehlen wir, die in Schritt 2 beschriebene Überprüfung durchzuführen, bevor Sie die Kompatibilitätsstufe auf 130 erhöhen.
Schritt 2: Identifizieren betroffener beibehaltener Strukturen
Ermitteln Sie, ob die Datenbank permanente Strukturen enthält, die von der verbesserten Genauigkeits- und Konvertierungslogik in Kompatibilitätsebene 130 in einer der folgenden Methoden betroffen sind:
DBCC CHECKDB WITH EXTENDED_LOGICAL_CHECKS
, die alle Strukturen in der Datenbank überprüft.DBCC CHECKTABLE WITH EXTENDED_LOGICAL_CHECKS
, die die Strukturen im Zusammenhang mit einer einzelnen Tabelle überprüft.
Die Option WITH EXTENDED_LOGICAL_CHECKS
ist erforderlich, um sicherzustellen, dass die dauerhaften Werte mit berechneten Werten verglichen werden, und um Fälle zu kennzeichnen, in denen ein Unterschied besteht. Da diese Prüfungen umfangreich sind, ist die Laufzeit von Anweisungen, die diese Option verwenden, länger als die Ausführung DBCC
von DBCC
Anweisungen ohne die Option. Daher empfiehlt DBCC CHECKTABLE
es sich, einzelne Tabellen anzuheften.
DBCC CHECKCONSTRAINTS
kann verwendet werden, um Einschränkungen zu überprüfen CHECK
. Diese Anweisung kann entweder auf Datenbank- oder Tabellenebene verwendet werden.
DBCC CHECK
Anweisungen sollten immer während eines Wartungsfensters ausgeführt werden, aufgrund der potenziellen Auswirkungen der Überprüfungen auf die Online-Workload.
Überprüfung auf Datenbankebene
Die Validierung auf Datenbankebene eignet sich für kleine und moderate Datenbanken. Verwenden Sie die Überprüfung auf Tabellenebene für große Datenbanken.
DBCC CHECKDB WITH EXTENDED_LOGICAL_CHECKS
wird verwendet, um alle dauerhaften Strukturen in der Datenbank zu überprüfen.
DBCC CHECKCONSTRAINTS
wird verwendet, um alle CHECK
Einschränkungen in der Datenbank zu überprüfen.
DBCC CHECKCONSTRAINTS
wird verwendet, um die Integrität von Einschränkungen zu überprüfen. Verwenden Sie das folgende Skript, um die Datenbank zu überprüfen:
USE [database_name]
GO
DBCC TRACEON(139, -1)
GO
DBCC CHECKCONSTRAINTS
GO
DBCC TRACEOFF(139, -1)
GO
Durch die Verwendung des Ablaufverfolgungskennzeichens wird sichergestellt, dass die Überprüfungen mithilfe der verbesserten Genauigkeits- und Konvertierungslogik durchgeführt werden, die sich in Kompatibilitätsebene 130 befindet, wodurch die richtige Konvertierungsemantik erzwungen wird, auch wenn die Datenbank über eine niedrigere Kompatibilitätsstufe verfügt.
Wenn die CHECKCONSTRAINTS
Anweisung abgeschlossen ist und kein Resultset zurückgibt, ist keine zusätzliche Aktion erforderlich.
Wenn die Anweisung ein Resultset zurückgibt, gibt jede Zeile in den Ergebnissen eine Verletzung einer Einschränkung an und enthält auch die Werte, die gegen die Einschränkung verstoßen.
- Speichern Sie die Namen der Tabellen und Einschränkungen zusammen mit den Werten, die den Verletzten verursacht haben (die
WHERE
Spalte im Resultset).
Das folgende Beispiel zeigt eine Tabelle mit einer CHECK
Einschränkung und eine einzelne Zeile, die die Einschränkung unter niedrigeren Kompatibilitätsstufen erfüllt, die jedoch gegen die Einschränkung unter Kompatibilitätsebene 130 verstößt.
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL=120
GO
CREATE TABLE dbo.table1
(
c2 datetime,
c3 datetime,
c4 int,
CONSTRAINT chk1 CHECK (c4= (DATEDIFF (ms, c2,c3)))
)
GO
INSERT dbo.table1 (c2, c3, c4) VALUES
(
convert(datetime, '1900-01-01 00:00:00.997'),
convert(datetime, '1900-01-01 00:00:01'), 3
)
GO
DBCC TRACEON(139, -1)
GO
DBCC CHECKCONSTRAINTS
GO
DBCC TRACEOFF(139, -1)
GO
Der CHECKCONSTRAINT
Befehl gibt die folgenden Ergebnisse zurück.
Tabelle | Einschränkung | Hierbei gilt: |
---|---|---|
[dbo]. [Tabelle1] | [chk1] | [c2] = '1900-01-01 00:00:00.997' AND [c3] = '1900-01-01 00:00:01.000' AND [c4] = '3' |
Dieses Ergebnis gibt an, dass die Einschränkung [chk1] für die Kombination von Spaltenwerten im Feld "Where" verletzt wird.
DBCC CHECKDB WITH EXTENDED_LOGICAL_CHECKS
DBCC CHECKDB WITH EXTENDED_LOGICAL_CHECKS
überprüft alle beibehaltenen Strukturen in der Datenbank. Dies ist die praktischste Option, da eine einzelne Anweisung alle Strukturen in der Datenbank überprüft. Diese Option eignet sich jedoch nicht für große Datenbanken aufgrund der erwarteten Laufzeit der Anweisung.
Verwenden Sie das folgende Skript, um die gesamte Datenbank zu überprüfen:
USE [database_name]
GO
DBCC TRACEON(139, -1)
GO
DBCC CHECKDB WITH EXTENDED_LOGICAL_CHECKS, NO_INFOMSGS, TABLERESULTS
GO
DBCC TRACEOFF(139, -1)
GO
Durch die Verwendung des Ablaufverfolgungskennzeichens wird sichergestellt, dass die Überprüfungen mithilfe der verbesserten Genauigkeits- und Konvertierungslogik durchgeführt werden, die sich in Kompatibilitätsebene 130 befindet, wodurch die richtige Konvertierungsemantik erzwungen wird, auch wenn die Datenbank über eine niedrigere Kompatibilitätsstufe verfügt.
Wenn die CHECKDB
Anweisung erfolgreich abgeschlossen wird, ist keine zusätzliche Aktion erforderlich.
Wenn die Anweisung mit Fehlern abgeschlossen ist, führen Sie die folgenden Schritte aus:
- Speichern Sie die Ergebnisse aus der Ausführung der
DBCC
Anweisung, die sich im Nachrichtenbereich in SQL Server Management Studio (SSMS) befindet, in einer Datei. - Überprüfen, ob alle gemeldeten Fehler mit dauerhaften Strukturen zusammenhängen
Tabelle 1: Beibehaltene Strukturen und entsprechende Fehlermeldungen für Inkonsistenzen
Strukturtyp betroffen | Beobachtete Fehlermeldungen | Notieren Sie sich |
---|---|---|
Gespeicherte berechnete Spalten | Msg 2537, Fehler der Ebene 16 Tabelle: Objekt-ID <object_id> , Index-ID <index_id> , . Fehler bei der Datensatzüberprüfung (gültige berechnete Spalte). Die Werte sind . | object_id> und Index-ID index_id <<> |
Indizes, die auf berechnete Spalten im Schlüssel verweisen oder spaltengefilterte Indizes enthalten | Msg 8951-Tabellenfehler: Tabelle "<table_name>" (ID <object_id>). Die Datenzeile enthält keine übereinstimmende Indexzeile im Index "<index_name>" (ID <index_id>) And/oder Msg 8952 Table error: table '<table_name>' (ID <table_name>). Indexzeile in Index '' (ID <index_id>) stimmt nicht mit einer Datenzeile überein. Darüber hinaus können sekundäre Fehler 8955 und/oder 8956 auftreten. Dies enthält Details zu den genauen Zeilen, die betroffen sind. Dies kann für diese Übung ignoriert werden. | object_id> und Index-ID index_id <<> |
Indizierte Sichten | Msg 8908 Die indizierte Ansicht "<view_name>" (Objekt-ID <object_id>) enthält nicht alle Zeilen, die die Ansichtsdefinition erzeugt. Und/oder Msg 8907 Die indizierte Ansicht "<view_name>" (Objekt-ID <object_id>) enthält Zeilen, die nicht von der Ansichtsdefinition erstellt wurden. | Objekt-ID <object_id> |
Wechseln Sie nach Abschluss der Überprüfung auf Datenbankebene zu Schritt 3.
Überprüfung auf Objektebene
Bei größeren Datenbanken ist es hilfreich, Strukturen und Einschränkungen für eine Tabelle oder eine Ansicht gleichzeitig zu überprüfen, um die Größe von Wartungsfenstern zu reduzieren oder die erweiterten logischen Prüfungen nur auf potenziell betroffene Objekte zu beschränken.
Verwenden Sie die Abfragen im Abschnitt Anhang C , um potenziell betroffene Tabellen zu identifizieren. Das Skript im Abschnitt Anhang D kann verwendet werden, um Auf der Grundlage der im Abschnitt Anhang C aufgeführten Abfragen zu generieren und CHECKCONSTRAINTS
Einschränkungen zu erstellenCHECKTABLE
.
DBCC CHECKCONSTRAINTS
Verwenden Sie das folgende Skript, um die Einschränkungen im Zusammenhang mit einer einzelnen Tabelle oder Ansicht zu überprüfen:
USE [database_name]
GO
DBCC TRACEON(139, -1)
GO
DBCC CHECKCONSTRAINTS()
GO
DBCC TRACEOFF(139, -1)
GO
Die Verwendung des Ablaufverfolgungskennzeichens stellt sicher, dass die Überprüfungen mithilfe der verbesserten Genauigkeits- und Konvertierungslogik durchgeführt werden, die sich in Kompatibilitätsebene 130 befindet, wodurch die verbesserte Semantik erzwungen wird, auch wenn die Datenbank über eine niedrigere Kompatibilitätsstufe verfügt.
Wenn die CHECKCONSTRAINTS
Anweisung abgeschlossen ist und kein Resultset zurückgibt, ist keine zusätzliche Aktion erforderlich.
Wenn die Anweisung ein Resultset zurückgibt, gibt jede Zeile in den Ergebnissen eine Verletzung einer Einschränkung an und stellt auch die Werte bereit, die gegen die Einschränkung verstoßen.
Speichern Sie die Namen der Tabellen und Einschränkungen zusammen mit den Werten, die den Verletzten verursacht haben (die WHERE
Spalte im Resultset).
DBCC CHECKTABLE WITH EXTENDED_LOGICAL_CHECKS
Verwenden Sie das folgende Skript, um die dauerhaften Strukturen zu überprüfen, die sich auf eine einzelne Tabelle oder Ansicht beziehen:
USE [database_name]
GO
DBCC TRACEON(139, -1)
GO
DBCC CHECKTABLE() WITH EXTENDED_LOGICAL_CHECKS, NO_INFOMSGS, TABLERESULTS
GO
DBCC TRACEOFF(139, -1)
GO
Wenn die CHECKTABLE
Anweisung erfolgreich abgeschlossen wird, ist keine zusätzliche Aktion erforderlich.
Wenn die Anweisung mit Fehlern abgeschlossen ist, führen Sie die folgenden Schritte aus:
- Speichern Sie die Ergebnisse aus der Ausführung der
DBCC
Anweisung, die im Nachrichtenbereich in SSMS gefunden wurde, in einer Datei. - Stellen Sie sicher, dass alle gemeldeten Fehler mit dauerhaften Strukturen zusammenhängen, wie in Tabelle 1 aufgeführt.
- Nachdem Sie die Überprüfung auf Tabellenebene abgeschlossen haben, fahren Sie mit Schritt 3 fort.
Schritt 3: Upgrade auf Kompatibilitätsebene 130
Wenn die Kompatibilitätsebene der Datenbank bereits 130 ist, können Sie diesen Schritt überspringen.
Die Kompatibilitätsebene der Datenbank kann mithilfe des folgenden Skripts in 130 geändert werden:
USE [database_name]
GO
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL=130
GO
Notiz
Da es Änderungen des Abfrageoptimierrs unter Kompatibilitätsebene 130 gibt, wird empfohlen, den Abfragespeicher zu aktivieren, bevor Sie die Kompatibilitätsstufe ändern. Weitere Informationen finden Sie im Abschnitt "Beibehalten der Leistungsstabilität während des Upgrades auf neuere SQL Server" in Abfragespeicher Verwendungsszenarien.
Schritt 4: Aktualisieren beibehaltener Strukturen
Wenn während der in Schritt 2 ausgeführten Überprüfung keine Inkonsistenzen gefunden wurden, sind Sie mit dem Upgrade fertig und können diesen Schritt überspringen. Wenn Inkonsistenzen in Schritt 2 gefunden wurden, sind zusätzliche Aktionen erforderlich, um die Inkonsistenzen aus der Datenbank zu entfernen. Die erforderlichen Aktionen hängen von der Art der betroffenen Struktur ab.
Wichtig
Führen Sie die Reparaturaktionen in diesem Schritt erst aus, nachdem die Datenbankkompatibilitätsebene in 130 geändert wurde.
Sichern der Datenbank (oder Datenbanken)
Es wird empfohlen, eine vollständige Datenbanksicherung durchzuführen, bevor Sie eine der im folgenden Abschnitt beschriebenen Aktionen ausführen. Wenn Sie Azure SQL-Datenbank verwenden, müssen Sie keine Sicherung selbst durchführen. Sie können die Point-in-Time-Wiederherstellungsfunktionalität immer verwenden, um in der Zeit zurückzukehren, falls bei einem der Updates ein Fehler auftritt.
CHECK-Einschränkungen
CHECK
Das Korrigieren von Einschränkungsverletzungen erfordert eine Änderung der Daten in der Tabelle oder der CHECK
Einschränkung selbst.
Aus dem Namen der Einschränkung (abgerufen in Schritt 2) können Sie die Einschränkungsdefinition wie folgt abrufen:
SELECT definition FROM sys.check_constraints
WHERE object_id= OBJECT_ID(N'constraint_name')
Um die betroffenen Tabellenzeilen zu prüfen, können Sie die Where-Informationen verwenden, die zuvor von der DBCC CHECKCONSTRAINTS
Anweisung zurückgegeben wurden:
SELECT *
FROM [schema_name].[table_name]
WHERE Where_clause
Sie müssen die betroffenen Zeilen entweder aktualisieren oder die Einschränkungsdefinition ändern, um sicherzustellen, dass die Einschränkung nicht verletzt wird.
Aktualisieren von Tabellendaten
Es gibt keine harte Regel, die angibt, wie die Daten aktualisiert werden sollen. Im Allgemeinen führen Sie für jede von ihnen zurückgegebene DBCC CHECKCONSTRAINTS
Where-Anweisung die folgende Update-Anweisung aus:
UPDATE [schema_name].[table_name] SET new_column_values
WHERE Where_clause
Betrachten Sie die folgende Beispieltabelle mit einer Einschränkung und einer Zeile, die gegen die Einschränkung in Kompatibilitätsebene 130 verstößt:
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL=120
GO
CREATE TABLE dbo.table1
(
c2 datetime,
c3 datetime,
c4 int,
CONSTRAINT chk1 CHECK (c4= (DATEDIFF (ms, c2, c3)))
)
GO
INSERT dbo.table1 (c2, c3, c4) VALUES
(convert(datetime, '1900-01-01 00:00:00.997'),
convert(datetime, '1900-01-01 00:00:01'), 3)
GO
In diesem Beispiel ist die Einschränkung einfach. Die Spalte c4
muss einem Ausdruck entsprechen, der beteiligt c2
ist und c3
. Um die Tabelle zu aktualisieren, weisen Sie diesen Wert zu c4
:
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL=130
GO
UPDATE dbo.table1 SET c4 = datediff (ms, c2,c3)
WHERE [c2] = '1900-01-01 00:00:00.997' AND [c3] = '1900-01-01 00:00:01.000' AND [c4] = '3'
GO
Beachten Sie, dass die WHERE
in der Update-Anweisung verwendete Klausel den where-Informationen entspricht, die von DBCC CHECKCONSTRAINTS
.
Aktualisieren der CHECK-Einschränkung
Um eine CHECK
Einschränkung zu ändern, müssen Sie sie ablegen und erneut erstellen. Es wird empfohlen, beide in derselben Transaktion auszuführen, falls probleme mit der aktualisierten Einschränkungsdefinition auftreten. Sie können die folgenden Transact-SQL-Daten verwenden:
BEGIN TRANSACTION
ALTER TABLE [schema_name].[table_name]
DROP CONSTRAINT [constraint_name]
ALTER TABLE [schema_name].[table_name]
ADD CONSTRAINT [constraint_name]
CHECK (new_constraint_definition)
COMMIT
GO
The following example updates the constraint chk1 in dbo.table1:
BEGIN TRANSACTION
ALTER TABLE dbo.table1
DROP CONSTRAINT chk1
ALTER TABLE dbo.table1
ADD CONSTRAINT chk1
CHECK (c4 <= DATEDIFF (ms, c2, c3))
COMMIT
GO
Gespeicherte berechnete Spalten
Die einfachste Möglichkeit zum Aktualisieren beibehaltener berechneter Spalten besteht darin, eine der Spalten zu aktualisieren, auf die von der berechneten Spalte verwiesen wird. Der neue Wert für die Spalte kann mit dem alten Wert identisch sein, sodass der Vorgang keine Benutzerdaten ändert.
Führen Sie diese Schritte für alle object_id
im Zusammenhang mit Inkonsistenzen in berechneten Spalten aus, die Sie in Schritt 2 angegeben haben.
Ermitteln berechneter Spalten:
Führen Sie die folgende Abfrage aus, um den Tabellennamen und die Namen der gespeicherten berechneten Spalten für die notierte abzurufen
object_id
:SELECT QUOTENAME(s.name) + N'.' + QUOTENAME(t.name) AS 'table', QUOTENAME(c1.name) AS 'persisted computed column', c1.column_id AS 'computed_column_id' , definition AS 'computed_column_definition' FROM sys.tables t JOIN sys.computed_columns c1 ON t.object_id=c1.object_id AND c1.is_persisted=1 JOIN sys.schemas s ON t.schema_id=s.schema_id WHERE t.object_id=object_id
Identifizieren von Spalten, auf die verwiesen wird:
Führen Sie die folgende Abfrage aus, um Spalten zu identifizieren, auf die von der berechneten Spalte verwiesen wird. Notieren Sie sich einen der Spaltennamen, auf die verwiesen wird:
SELECT QUOTENAME(s.name) + N'.' + QUOTENAME(o.name) AS 'referencing object', o.type_desc AS 'object type', referenced_minor_id AS 'referenced_column_id', c.name AS 'referenced_column_name' FROM sys.sql_expression_dependencies sed JOIN sys.computed_columns c1 ON sed.referencing_id=c1.object_id AND sed.referencing_minor_id=c1.column_id JOIN sys.objects o ON sed.referencing_id=o.object_id JOIN sys.schemas s ON o.schema_id=s.schema_id JOIN sys.columns c ON o.object_id=c.object_id AND sed.referenced_minor_id=c.column_id WHERE referencing_class=1 AND referenced_class=1 AND referencing_id=object_id AND referencing_minor_id=computed_column_id
Führen Sie eine
UPDATE
Anweisung aus, die eine der referenzierten Spalten umfasst, um eine Aktualisierung der berechneten Spalte auszulösen:Die folgende Anweisung löst eine Aktualisierung der Spalte aus, auf die von der berechneten Spalte verwiesen wird, und löst außerdem eine Aktualisierung der berechneten Spalte aus.
UPDATE [schema_name].[table_name] SET referenced_column_name=ISNULL(referenced_column_name, referenced_column_name)
Der
ISNULL
Ausdruck in der Anweisung wird so gestaltet, dass der Wert der ursprünglichen Spalte nicht geändert wird, während gleichzeitig sichergestellt wird, dass die berechnete Spalte mithilfe der Auswertungslogik der DB-Kompatibilitätsebene 130 aktualisiert wird.Beachten Sie, dass Sie bei sehr großen Tabellen möglicherweise nicht alle Zeilen in einer einzelnen Transaktion aktualisieren möchten. In einem solchen Fall können Sie die Aktualisierung in Batches ausführen, indem Sie der Update-Anweisung eine
WHERE
Klausel hinzufügen, die einen Zeilenbereich identifiziert, z. B. basierend auf dem Primärschlüssel.
Identifizieren Sie Indizes, die auf die berechnete Spalte verweisen.
SELECT i.name AS [index name] FROM sys.index_columns ic JOIN sys.indexes i ON ic.object_id=i.object_id AND ic.index_id=i.index_id WHERE i.object_id=object_id AND ic.column_id=computed_column_id
Diese Abfrage identifiziert alle Indizes, die auf die gespeicherte berechnete Spalte verweisen. Ein solcher Index muss neu erstellt werden. Führen Sie dazu die Schritte im folgenden Abschnitt aus.
Indizes, gefilterte Indizes und indizierte Ansichten
Inkonsistenzen in Indizes entsprechen Fehlern 8951 und 8952 (für Tabellen) oder 8907 und 8908 (für Ansichten) in der DBCC CHECK
Ausgabe von Schritt 2.
Führen Sie zum DBCC CHECKTABLE
Reparieren dieser Inkonsistenzen mit REPAIR_REBUILD
. Dadurch werden die Indizes ohne Datenverlust repariert. Die Datenbank muss sich jedoch im Einzelbenutzermodus befinden und ist daher für andere Benutzer nicht verfügbar, während die Reparatur erfolgt.
Sie können auch betroffene Indizes manuell neu erstellen. Diese Option sollte verwendet werden, wenn die Workload nicht offline geschaltet werden kann, da die Indexneuerstellung als ONLINE-Vorgang (in unterstützten Editionen von SQL Server) ausgeführt werden kann.
Neuerstellen von Indizes
Wenn das Festlegen der Datenbank im Einzelbenutzermodus keine Option ist, können Sie Indizes einzeln neu erstellen, indem ALTER INDEX REBUILD
Sie für jeden in Schritt 2 identifizierten Index verwenden.
Verwenden Sie die folgende Abfrage, um die Tabellen- und Indexnamen für eine bestimmte object_id
und index_id
.
SELECT QUOTENAME(SCHEMA_NAME(o.schema_id)) + N'.' + QUOTENAME(o.name) AS 'table', i.name AS 'index_name'
FROM sys.objects o JOIN sys.indexes i ON o.object_id=i.object_id
WHERE o.object_id = object_id AND i.index_id = index_id
Verwenden Sie die folgende Anweisung, um den Index neu zu erstellen:
ALTER INDEX index_name ON [schema_name].[table_name] REBUILD WITH (ONLINE=ON)
Notiz
Wenn Sie Standard-, Web- oder Express-Editionen verwenden, wird der Onlineindexbuild nicht unterstützt. Daher muss die Option WITH (ONLINE=ON)
aus der ALTER INDEX
Anweisung entfernt werden.
Das folgende Beispiel zeigt die Neuerstellung eines gefilterten Indexes:
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL=120
GO
CREATE TABLE dbo.table2
(
c2 datetime,
c3 float
)
GO
INSERT dbo.table2 (c2,c3) VALUES ('1899-12-31 23:58:00.470', -0.00138344907407406)
GO
CREATE INDEX ix_1 ON dbo.table2(c2)
WHERE (c2=-0.00138344907407406)
GO
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL=130GOALTER INDEX ix_1 ON [dbo].[table2] REBUILD WITH (ONLINE=ON)
GO
Wenn Sie über regelmäßige Wartungspläne verfügen, empfehlen wir, diesen Index als Teil Der geplanten Wartung einzubeziehen.
Reparieren mithilfe von DBCC
Führen Sie für jedes (object_id) im Zusammenhang mit einem Index mit Inkonsistenzen aus, die Sie in Schritt 2 angegeben haben, das folgende Skript, um die Reparatur auszuführen. Dieses Skript legt die Datenbank im Einzelbenutzermodus für den Reparaturvorgang fest. Im schlimmsten Fall führt die Reparatur eine vollständige Indexneuerstellung durch.
USE [database_name]
GO
ALTER DATABASE CURRENT SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
DBCC CHECKTABLE (object_id, REPAIR_REBUILD) WITH EXTENDED_LOGICAL_CHECKS, NO_INFOMSGS, TABLERESULTS
GO
ALTER DATABASE CURRENT SET MULTI_USER
GO
Anhang C: Abfragen zur Identifizierung von Kandidatentabellen
Die folgenden Skripts identifizieren Kandidatentabellen, die Sie anhand der Existenz beibehaltener Strukturen und Einschränkungen überprüfen möchten DBCC CHECKTABLE WITH EXTENDED_LOGICAL_CHECKS
, die von den Verbesserungen der Kompatibilitätsebene 130 betroffener Datentypen betroffen sind.
Die folgenden Abfragelistendetails zu den Tabellen und potenziell betroffenen Strukturen, die eine zusätzliche Überprüfung erfordern.
Indizierte Sichten
Die folgende Abfrage gibt alle indizierten Ansichten zurück, die auf Spalten verweisen, indem betroffene Datentypen oder eine der betroffenen integrierten Funktionen verwendet wird:
SELECT QUOTENAME(SCHEMA_NAME(o.schema_id)) + N'.' + QUOTENAME(o.name) AS 'view', QUOTENAME(i.name) AS 'index',QUOTENAME(sed.referenced_schema_name) + N'.' + QUOTENAME(sed.referenced_entity_name) AS 'referenced table', QUOTENAME(c.name) AS 'referenced column', t.name AS 'data type',
-- if the data type is numeric, integer, or money, the only cases that warrent additional checks
-- with DBCC is if the view definition contains a float or datetime value, or a conversion to such value
s.definition
FROM sys.sql_expression_dependencies sed
JOIN sys.objects o ON sed.referencing_id = o.object_id AND o.type=N'V'
JOIN sys.indexes i ON o.object_id=i.object_id
JOIN sys.sql_modules s ON s.object_id=o.object_id
JOIN sys.columns c ON sed.referenced_id=c.object_id AND sed.referenced_minor_id=c.column_idJOIN sys.types t ON c.system_type_id=t.system_type_id
WHERE referencing_class=1 AND referenced_class=1 AND (c.system_type_id IN
( 59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint
) OR s.[definition] LIKE '%DATEDIFF%'
OR s.[definition] LIKE '%CONVERT%'
OR s.[definition] LIKE '%CAST%'
OR s.[definition] LIKE '%DATEPART%'
OR s.[definition] LIKE '%DEGREES%')
Gespeicherte berechnete Spalten
Die folgende Abfrage gibt alle Tabellen mit berechneten Spalten zurück, die auf andere Spalten verweisen, indem sie betroffene Datentypen verwenden oder eine der betroffenen integrierten Funktionen verwenden, wobei entweder die Spalte beibehalten oder aus einem Index verwiesen wird.
SELECT QUOTENAME(sed.referenced_schema_name) + N'.' +
QUOTENAME(sed.referenced_entity_name) AS 'candidate table with computed column',
QUOTENAME(c1.name) AS 'computed column', c1.is_persisted,QUOTENAME(c2.name) AS 'referenced column', t.name AS 'data type',
-- if the data type is numeric, integer, or money, the only cases that warrent additional checks
-- with DBCC is if the column definition contains a float or datetime value, or a conversion to such value
c1.definition
FROM sys.sql_expression_dependencies sed
JOIN sys.computed_columns c1 ON sed.referencing_id=c1.object_id AND sed.referencing_minor_id=c1.column_id
JOIN sys.columns c2 ON sed.referenced_id=c2.object_id AND sed.referenced_minor_id=c2.column_id
JOIN sys.types t ON c2.system_type_id=t.system_type_idWHERE referencing_class=1 AND referenced_class=1
AND (c2.system_type_id IN
( 59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint
) OR c1.[definition] LIKE '%DATEDIFF%'
OR c1.[definition] LIKE '%CONVERT%'
OR c1.[definition] LIKE '%DATEPART%'
OR c1.[definition] LIKE '%DEGREES%')
AND (
-- the column is persisted
c1.is_persisted=1
-- OR the column is included in an index
OR EXISTS (SELECT 1 FROM sys.index_columns ic WHERE ic.object_id=c1.object_id AND ic.column_id=c1.column_id)
)
Gefilterte Indizes
Die folgende Abfrage gibt alle Tabellen mit gefilterten Indizes zurück, die auf Spalten in der Filterbedingung verweisen, die betroffene Datentypen aufweisen:
SELECT QUOTENAME(sed.referenced_schema_name) + N'.' +
QUOTENAME(sed.referenced_entity_name) AS 'candidate table with filtered index',
QUOTENAME(i.name) AS 'referencing index',
QUOTENAME(c.name) AS 'referenced column',
t.name AS 'data type',
-- if the data type is numeric, integer, or money, the only cases that warrent additional checks
-- with DBCC is where the filter condition contains a float or datetime value
i.filter_definition AS 'filter condition'
FROM sys.sql_expression_dependencies sed
JOIN sys.indexes i ON sed.referencing_id=i.object_id AND sed.referencing_minor_id=i.index_id
JOIN sys.columns c ON sed.referenced_id=c.object_id AND sed.referenced_minor_id=c.column_id
JOIN sys.types t ON c.system_type_id=t.system_type_id
WHERE referencing_class=7 AND referenced_class=1 AND i.has_filter=1
AND c.system_type_id IN ( 59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint
)
Check-Einschränkungen
Die folgende Abfrage listet alle Tabellen mit Prüfeinschränkungen auf, die auf betroffene Datentypen oder integrierte Funktionen verweisen:
SELECT QUOTENAME(sed.referenced_schema_name) + N'.' +
QUOTENAME(sed.referenced_entity_name) AS 'candidate table with check constraint',
QUOTENAME(c.name) AS 'constraint_name', c.definition AS 'constraint_definition',
QUOTENAME(col.name) AS 'referenced column', t.name AS 'data type'
FROM sys.sql_expression_dependencies sed
JOIN sys.check_constraints c ON sed.referencing_id=c.object_id AND sed.referencing_class=1
JOIN sys.columns col ON sed.referenced_id=col.object_id AND sed.referenced_minor_id=col.column_id
JOIN sys.types t ON col.system_type_id=t.system_type_id
WHERE referencing_class=1 AND referenced_class=1 AND (col.system_type_id IN
( 59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint)
OR c.[definition] LIKE '%DATEDIFF%'
OR c.[definition] LIKE '%CONVERT%'
OR c.[definition] LIKE '%DATEPART%'
OR c.[definition] LIKE '%DEGREES%')
Anhang D: Skript zum Erstellen von CHECK*-Anweisungen
Das folgende Skript kombiniert die Abfragen aus dem vorherigen Anhang und vereinfacht die Ergebnisse, indem eine Liste von Tabellen und Ansichten in Form von CHECKCONSTRAINTS
und CHECKTABLE
Anweisungen dargestellt wird.
DECLARE @CRLF nvarchar(10) = CHAR(13) + CHAR(10);
DECLARE @sql nvarchar(max) = N'DBCC TRACEON(139,-1); ' + @CRLF ;
SELECT @sql += N'DBCC CHECKTABLE (N''' + object_for_checktable + N''') WITH EXTENDED_LOGICAL_CHECKS, NO_INFOMSGS, TABLERESULTS; ' + @CRLF
FROM
(
--indexed views
SELECT DISTINCT QUOTENAME(SCHEMA_NAME(o.schema_id)) + N'.' + QUOTENAME(o.name) AS 'object_for_checktable'
FROM sys.sql_expression_dependencies AS sed
INNER JOIN sys.objects AS o ON sed.referencing_id = o.object_id AND o.type = N'V'
INNER JOIN sys.indexes AS i ON o.object_id = i.object_id
INNER JOIN sys.sql_modules AS s ON s.object_id = o.object_id
INNER JOIN sys.columns AS c ON sed.referenced_id = c.object_id AND sed.referenced_minor_id = c.column_id
INNER JOIN sys.types AS t ON c.system_type_id = t.system_type_id
WHERE referencing_class = 1 AND referenced_class=1
AND (c.system_type_id IN
( 59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint
) OR s.[definition] LIKE N'%DATEDIFF%'
OR s.[definition] LIKE N'%CONVERT%'
OR s.[definition] LIKE N'%CAST%'
OR s.[definition] LIKE N'%DATEPART%'
OR s.[definition] LIKE N'%DEGREES%')
UNION
--persisted computed columns
SELECT DISTINCT QUOTENAME(sed.referenced_schema_name) + N'.' + QUOTENAME(sed.referenced_entity_name) AS 'object_for_checktable'
FROM sys.sql_expression_dependencies AS sed
INNER JOIN sys.computed_columns AS c1 ON sed.referencing_id = c1.object_id AND sed.referencing_minor_id = c1.column_id
INNER JOIN sys.columns AS c2 ON sed.referenced_id=c2.object_id AND sed.referenced_minor_id = c2.column_id
INNER JOIN sys.types AS t ON c2.system_type_id = t.system_type_id
WHERE referencing_class = 1 AND referenced_class = 1
AND (c2.system_type_id IN
( 59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint
) OR c1.[definition] LIKE N'%DATEDIFF%'
OR c1.[definition] LIKE N'%CONVERT%'
OR c1.[definition] LIKE N'%DATEPART%'
OR c1.[definition] LIKE N'%DEGREES%')
AND (
-- the column is persisted
c1.is_persisted = 1
-- OR the column is included in an index
OR EXISTS (SELECT 1 FROM sys.index_columns AS ic
WHERE ic.object_id = c1.object_id AND ic.column_id=c1.column_id)
)
UNION
--indexed views
SELECT DISTINCT QUOTENAME(sed.referenced_schema_name) + N'.' + QUOTENAME(sed.referenced_entity_name) AS 'object_for_checktable'
FROM sys.sql_expression_dependencies AS sed
INNER JOIN sys.indexes AS i ON sed.referencing_id = i.object_id AND sed.referencing_minor_id = i.index_id
INNER JOIN sys.columns AS c ON sed.referenced_id = c.object_id AND sed.referenced_minor_id = c.column_id
INNER JOIN sys.types AS t ON c.system_type_id = t.system_type_id
WHERE referencing_class = 7 AND referenced_class = 1 AND i.has_filter = 1
AND c.system_type_id IN (
59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint
)) AS a
SELECT @sql += N'DBCC CHECKCONSTRAINTS (N''' + object_for_checkconstraints + N'''); ' + @CRLF
FROM
(
SELECT DISTINCT QUOTENAME(sed.referenced_schema_name) + N'.' + QUOTENAME(sed.referenced_entity_name) AS 'object_for_checkconstraints'
FROM sys.sql_expression_dependencies AS sed
INNER JOIN sys.check_constraints AS c ON sed.referencing_id = c.object_id AND sed.referencing_class = 1
INNER JOIN sys.columns AS col ON sed.referenced_id = col.object_id AND sed.referenced_minor_id = col.column_id
INNER JOIN sys.types AS t ON col.system_type_id = t.system_type_id
WHERE referencing_class = 1 AND referenced_class = 1 AND (col.system_type_id IN
( 59 --real
, 62 --float
, 58 --smalldatetime
, 61 --datetime
, 60 --money
, 122 --smallmoney
, 106 --decimal
, 108 --numeric
, 56 --int
, 48 --tinyint
, 52 -- smallint
, 41 --time
, 127 --bigint
) OR c.[definition] LIKE N'%DATEDIFF%'
OR c.[definition] LIKE N'%CONVERT%'
OR c.[definition] LIKE N'%DATEPART%'
OR c.[definition] LIKE N'%DEGREES%')
) a
SET @sql += N'DBCC TRACEOFF(139,-1);';
PRINT @sql;
--to run the script immediately, use the following command:
--EXECUTE sp_executesql @sql;
GO