Warum wird diese Abfrage in einer TVF-Datei drastisch langsamer?


17

Ich habe eine ziemlich komplexe Abfrage, die von sich aus in wenigen Sekunden ausgeführt wird, aber wenn sie in eine Tabellenfunktion eingebunden ist, ist sie weitaus langsamer. Ich habe es eigentlich nicht zu Ende gebracht, aber es läuft bis zu zehn Minuten ohne Ende. Die einzige Änderung besteht darin, zwei Datumsvariablen (initialisiert mit Datumsliteralen) durch Datumsparameter zu ersetzen:

Läuft in sieben Sekunden

DECLARE @StartDate DATE = '2011-05-21'
DECLARE @EndDate   DATE = '2011-05-23'

DECLARE @Data TABLE (...)
INSERT INTO @Data(...) SELECT...

SELECT * FROM @Data

Läuft für mindestens zehn Minuten

CREATE FUNCTION X (@StartDate DATE, @EndDate DATE)
  RETURNS TABLE AS RETURN
  SELECT ...

SELECT * FROM X ('2011-05-21', '2011-05-23')

Ich hatte zuvor die Funktion als TVF mit mehreren Anweisungen mit einer RETURNS @Data TABLE (...) -Klausel geschrieben, aber das Austauschen dieser Funktion für die Inline-Struktur hat keine nennenswerte Änderung bewirkt. Die langfristige Laufzeit des TVF ist die tatsächliche SELECT * FROM XZeit. Das Erstellen der UDF dauert nur wenige Sekunden.

Ich könnte die fragliche Abfrage posten, aber sie ist etwas lang (~ 165 Zeilen) und ich vermute, dass aufgrund des Erfolgs des ersten Ansatzes noch etwas anderes im Gange ist. Durchsuchen Sie die Ausführungspläne, sie scheinen identisch zu sein.

Ich habe versucht, die Abfrage ohne Änderung in kleinere Abschnitte zu unterteilen. Kein einzelner Abschnitt dauert länger als ein paar Sekunden, wenn er alleine ausgeführt wird, aber der TVF bleibt hängen.

Ich sehe eine sehr ähnliche Frage: /programming/4190506/sql-server-2005-table-valued-function-weird-performance , bin mir aber nicht sicher, ob die Lösung zutrifft. Vielleicht hat jemand dieses Problem gesehen und kennt eine allgemeinere Lösung? Vielen Dank!

Hier sind die dm_exec_requests nach einigen Minuten der Verarbeitung:

session_id              59
request_id              0
start_time              40688.46517
status                  running
command                 UPDATE
sql_handle              0x030015002D21AF39242A1101ED9E00000000000000000000
statement_start_offset  10962
statement_end_offset    16012
plan_handle             0x050015002D21AF3940C1E6B0040000000000000000000000
database_id                 21
user_id                 1
connection_id           314AE0E4-A1FB-4602-BF40-02D857BAD6CF
blocking_session_id         0
wait_type               NULL
wait_time                   0
last_wait_type          SOS_SCHEDULER_YIELD
wait_resource   
open_transaction_count  0
open_resultset_count    1
transaction_id              48030651
context_info            0x
percent_complete        0
estimated_completion_time   0
cpu_time                    344777
total_elapsed_time          348632
scheduler_id            7
task_address            0x000000045FC85048
reads                   1549
writes                  13
logical_reads           30331425
text_size               2147483647
language                us_english
date_format             mdy
date_first              7
quoted_identifier           1
arithabort              1
ansi_null_dflt_on       1
ansi_defaults           0
ansi_warnings           1
ansi_padding            1
ansi_nulls                  1
concat_null_yields_null 1
transaction_isolation_level 2
lock_timeout            -1
deadlock_priority           0
row_count                   105
prev_error              0
nest_level              1
granted_query_memory    170
executing_managed_code  0
group_id                2
query_hash              0xBE6A286546AF62FC
query_plan_hash         0xD07630B947043AF0

Hier ist die vollständige Abfrage:

CREATE FUNCTION Routine.MarketingDashboardECommerceBase (@StartDate DATE, @EndDate DATE)
RETURNS TABLE AS RETURN
    WITH RegionsByCode AS (SELECT CountryCode, MIN(Region) AS Region FROM Staging.Volusion.MarketingRegions GROUP BY CountryCode)
        SELECT
            D.Date, Div.Division, Region.Region, C.Category1, C.Category2, C.Category3,
            COALESCE(V.Visits,          0) AS Visits,
            COALESCE(Dem.Demos,         0) AS Demos,
            COALESCE(S.GrossStores,     0) AS GrossStores,
            COALESCE(S.PaidStores,      0) AS PaidStores,
            COALESCE(S.NetStores,       0) AS NetStores,
            COALESCE(S.StoresActiveNow, 0) AS StoresActiveNow
            -- This line causes the run time to climb from a few seconds to over an hour!
            --COALESCE(V.Visits,          0) * COALESCE(ACS.AvgClickCost, GAAC.AvgAdCost, 0.00) AS TotalAdCost
            -- This line alone does not inflate the run time
            --ACS.AvgClickCost
            -- This line is enough to increase the run time to at least a couple minutes
            --GAAC.AvgAdCost
        FROM
            --Dates AS D
            (SELECT SQLDate AS Date FROM Dates WHERE SQLDate BETWEEN @StartDate AND @EndDate) AS D
            CROSS JOIN (SELECT 'UK' AS Division UNION SELECT 'US' UNION SELECT 'IN' UNION SELECT 'Unknown') AS Div
            CROSS JOIN (SELECT Category1, Category2, Category3 FROM Routine.MarketingDashboardCampaignMap UNION SELECT 'Unknown', 'Unknown', 'Unknown') AS C
            CROSS JOIN (SELECT DISTINCT Region FROM Staging.Volusion.MarketingRegions) AS Region
            -- Visitors
            LEFT JOIN
                (
                SELECT
                    V.Date,
                    CASE    WHEN V.Country IN ('United Kingdom', 'Guernsey', 'Ireland', 'Jersey') THEN 'UK'
                        WHEN V.Country IN ('United States', 'Canada', 'Puerto Rico', 'U.S. Virgin Islands') THEN 'US'
                        ELSE 'IN' END AS Division,
                    COALESCE(MR.Region, 'Unknown') AS Region,
                    C.Category1, C.Category2, C.Category3,
                    SUM(V.Visits) AS Visits
                FROM
                             RawData.GoogleAnalytics.Visits        AS V
                    INNER JOIN Routine.MarketingDashboardCampaignMap AS C ON V.LandingPage = C.LandingPage AND V.Campaign = C.Campaign AND V.Medium = C.Medium AND V.Referrer = C.Referrer AND V.Source = C.Source
                    LEFT JOIN  Staging.Volusion.MarketingRegions     AS MR ON V.Country = MR.CountryName
                WHERE
                    V.Date BETWEEN @StartDate AND @EndDate
                GROUP BY
                    V.Date,
                    CASE    WHEN V.Country IN ('United Kingdom', 'Guernsey', 'Ireland', 'Jersey') THEN 'UK'
                        WHEN V.Country IN ('United States', 'Canada', 'Puerto Rico', 'U.S. Virgin Islands') THEN 'US'
                        ELSE 'IN' END,
                    COALESCE(MR.Region, 'Unknown'), C.Category1, C.Category2, C.Category3
                ) AS V ON D.Date = V.Date AND Div.Division = V.Division AND Region.Region = V.Region AND C.Category1 = V.Category1 AND C.Category2 = V.Category2 AND C.Category3 = V.Category3
            -- Demos
            LEFT JOIN
                (
                SELECT
                    OD.SQLDate,
                    G.Division,
                    COALESCE(MR.Region,   'Unknown') AS Region,
                    COALESCE(C.Category1, 'Unknown') AS Category1,
                    COALESCE(C.Category2, 'Unknown') AS Category2,
                    COALESCE(C.Category3, 'Unknown') AS Category3,
                    SUM(D.Demos) AS Demos
                FROM
                             Demos            AS D
                    INNER JOIN Orders           AS O  ON D."Order" = O."Order"
                    INNER JOIN Dates            AS OD ON O.OrderDate = OD.DateSerial
                    INNER JOIN MarketingSources AS MS ON D.Source = MS.Source
                    LEFT JOIN  RegionsByCode    AS MR ON MS.CountryCode = MR.CountryCode
                    LEFT JOIN
                        (
                        SELECT
                            G.TransactionID,
                            MIN (
                                CASE WHEN G.Country IN ('United Kingdom', 'Guernsey', 'Ireland', 'Jersey') THEN 'UK'
                                    WHEN G.Country IN ('United States', 'Canada', 'Puerto Rico', 'U.S. Virgin Islands') THEN 'US'
                                    ELSE 'IN' END
                                ) AS Division
                        FROM
                            RawData.GoogleAnalytics.Geography AS G
                        WHERE
                                TransactionDate BETWEEN @StartDate AND @EndDate
                            AND NOT EXISTS (SELECT * FROM RawData.GoogleAnalytics.Geography AS G2 WHERE G.TransactionID = G2.TransactionID AND G2.EffectiveDate > G.EffectiveDate)
                        GROUP BY
                            G.TransactionID
                        ) AS G  ON O.VolusionOrderID = G.TransactionID
                    LEFT JOIN  RawData.GoogleAnalytics.Referrers     AS R  ON O.VolusionOrderID = R.TransactionID AND NOT EXISTS (SELECT * FROM RawData.GoogleAnalytics.Referrers AS R2 WHERE R.TransactionID = R2.TransactionID AND R2.EffectiveDate > R.EffectiveDate)
                    LEFT JOIN  Routine.MarketingDashboardCampaignMap AS C  ON MS.LandingPage = C.LandingPage AND MS.Campaign = C.Campaign AND MS.Medium = C.Medium AND COALESCE(R.ReferralPath, '(not set)') = C.Referrer AND MS.SourceName = C.Source
                WHERE
                        O.IsDeleted = 'No'
                    AND OD.SQLDate BETWEEN @StartDate AND @EndDate
                GROUP BY
                    OD.SQLDate,
                    G.Division,
                    COALESCE(MR.Region,   'Unknown'),
                    COALESCE(C.Category1, 'Unknown'),
                    COALESCE(C.Category2, 'Unknown'),
                    COALESCE(C.Category3, 'Unknown')
                ) AS Dem ON D.Date = Dem.SQLDate AND Div.Division = Dem.Division AND Region.Region = Dem.Region AND C.Category1 = Dem.Category1 AND C.Category2 = Dem.Category2 AND C.Category3 = Dem.Category3
            -- Stores
            LEFT JOIN
                (
                SELECT
                    OD.SQLDate,
                    CASE WHEN O.VolusionCountryCode = 'GB' THEN 'UK'
                        WHEN A.CountryShortName IN ('U.S.', 'Canada', 'Puerto Rico', 'U.S. Virgin Islands') THEN 'US'
                        ELSE 'IN' END AS Division,
                    COALESCE(MR.Region,     'Unknown') AS Region,
                    COALESCE(CpM.Category1, 'Unknown') AS Category1,
                    COALESCE(CpM.Category2, 'Unknown') AS Category2,
                    COALESCE(CpM.Category3, 'Unknown') AS Category3,
                    SUM(S.Stores) AS GrossStores,
                    SUM(CASE WHEN O.DatePaid <> -1 THEN 1 ELSE 0 END) AS PaidStores,
                    SUM(CASE WHEN O.DatePaid <> -1 AND CD.WeekEnding <> OD.WeekEnding THEN 1 ELSE 0 END) AS NetStores,
                    SUM(CASE WHEN O.DatePaid <> -1 THEN SH.ActiveStores ELSE 0 END) AS StoresActiveNow
                FROM
                             Stores           AS S
                    INNER JOIN Orders           AS O   ON S."Order" = O."Order"
                    INNER JOIN Dates            AS OD  ON O.OrderDate = OD.DateSerial
                    INNER JOIN Dates            AS CD  ON O.CancellationDate = CD.DateSerial
                    INNER JOIN Customers        AS C   ON O.CustomerNow = C.Customer
                    INNER JOIN MarketingSources AS MS  ON C.Source = MS.Source
                    INNER JOIN StoreHistory     AS SH  ON S.MostRecentHistory = SH.History
                    INNER JOIN Addresses        AS A   ON C.Address = A.Address
                    LEFT JOIN  RegionsByCode    AS MR  ON MS.CountryCode = MR.CountryCode
                    LEFT JOIN  Routine.MarketingDashboardCampaignMap AS CpM ON CpM.LandingPage = 'N/A' AND MS.Campaign = CpM.Campaign AND MS.Medium = CpM.Medium AND CpM.Referrer = 'N/A' AND MS.SourceName = CpM.Source
                WHERE
                        O.IsDeleted = 'No'
                    AND OD.SQLDate BETWEEN @StartDate AND @EndDate
                GROUP BY
                    OD.SQLDate,
                    CASE WHEN O.VolusionCountryCode = 'GB' THEN 'UK'
                        WHEN A.CountryShortName IN ('U.S.', 'Canada', 'Puerto Rico', 'U.S. Virgin Islands') THEN 'US'
                        ELSE 'IN' END,
                    COALESCE(MR.Region,     'Unknown'),
                    COALESCE(CpM.Category1, 'Unknown'),
                    COALESCE(CpM.Category2, 'Unknown'),
                    COALESCE(CpM.Category3, 'Unknown')
                ) AS S ON D.Date = S.SQLDate AND Div.Division = S.Division AND Region.Region = S.Region AND C.Category1 = S.Category1 AND C.Category2 = S.Category2 AND C.Category3 = S.Category3
            -- Google Analytics spend
            LEFT JOIN
                (
                SELECT
                    AC.Date, C.Category1, C.Category2, C.Category3, SUM(AC.AdCost) / SUM(AC.Visits) AS AvgAdCost
                FROM
                    RawData.GoogleAnalytics.AdCosts AS AC
                    INNER JOIN
                        (
                        SELECT Campaign, Medium, Source, MIN(Category1) AS Category1, MIN(Category2) AS Category2, MIN(Category3) AS Category3
                        FROM Routine.MarketingDashboardCampaignMap
                        WHERE Category1 <> 'Affiliate'
                        GROUP BY Campaign, Medium, Source
                        ) AS C ON AC.Campaign = C.Campaign AND AC.Medium = C.Medium AND AC.Source = C.Source
                WHERE
                    AC.Date BETWEEN @StartDate AND @EndDate
                GROUP BY
                    AC.Date, C.Category1, C.Category2, C.Category3
                HAVING
                    SUM(AC.AdCost) > 0.00 AND SUM(AC.Visits) > 0
                ) AS GAAC ON D.Date = GAAC.Date AND C.Category1 = GAAC.Category1 AND C.Category2 = GAAC.Category2 AND C.Category3 = GAAC.Category3
            -- adCenter spend
            LEFT JOIN
                (
                SELECT Date, SUM(Spend) / SUM(Clicks) AS AvgClickCost
                FROM RawData.AdCenter.Spend
                WHERE Date BETWEEN @StartDate AND @EndDate
                GROUP BY Date
                HAVING SUM(Spend) > 0.00 AND SUM(Clicks) > 0
                ) AS ACS ON D.Date = ACS.Date AND C.Category1 = 'PPC' AND C.Category2 = 'adCenter' AND C.Category3 = 'N/A'
        WHERE
            V.Visits > 0 OR Dem.Demos > 0 OR S.GrossStores > 0
GO


SELECT * FROM Routine.MarketingDashboardECommerceBase('2011-05-21', '2011-05-23')

Können Sie uns bitte die Pläne für die Textabfrage zeigen? Und in der ersten Abfrage, welche Typen sind @StartDate + @EndDate
gbn

@gbn: Entschuldigung, der Plan ist mit ca. 32K Zeichen zu lang. Gibt es eine Untermenge, die am nützlichsten wäre? Möchten Sie auch den Plan für die eigenständige Abfrage oder die TVF bevorzugen?
Jon of All Trades

Wenn Sie den Ausführungsplan für das TVF-Formular der Abfrage ausführen, werden keine nützlichen Informationen zurückgegeben. Ich gehe daher davon aus, dass Sie nach dem Abfrageplan für die Nicht-TVF-Version suchen. Oder gibt es eine Möglichkeit, zu dem von einem TVF tatsächlich verwendeten Ausführungsplan zu gelangen?
Jon of All Trades

Keine wartenden Aufgaben. Ich bin nicht mit dm_exec_requests vertraut, aber ich habe die Ausgabe ab der Fünf-Minuten-Marke in der TVF-Ausführung angehängt.
Jon of All Trades

@ Martin: Ja; Die eigenständige Abfrage hatte eine CPU-Zeit von 7021 (2% der TVF- Teilversion ) und 154 KB logische Lesevorgänge (0,5%). Ich habe kürzlich die TVF-Version verlassen, um sie auszuführen, und sie war nach 27 Minuten beendet. Es werden also definitiv viel mehr Daten verarbeitet ... aber wie kann ich dafür sorgen, dass ein besserer Plan verwendet wird? Ich werde den guten Ausführungsplan im Detail studieren und sehen, ob ein paar Tipps helfen.
Jon of All Trades

Antworten:


3

Ich habe das Problem auf eine Zeile in der Abfrage beschränkt. Beachten Sie, dass die Abfrage 160 Zeilen lang ist und ich die relevanten Tabellen in beiden Fällen einbeziehe, wenn ich diese Zeile in der SELECT-Klausel deaktiviere:

COALESCE(V.Visits, 0) * COALESCE(ACS.AvgClickCost, GAAC.AvgAdCost, 0.00)

... die Laufzeit von 63 Minuten auf fünf Sekunden sinkt (Inlining eines CTE hat es etwas schneller als die ursprüngliche 7-Sekunden-Abfrage gemacht). Das Einbeziehen von entweder ACS.AvgClickCostoder GAAC.AvgAdCostführt dazu, dass die Laufzeit explodiert. Was es besonders merkwürdig macht, ist, dass diese Felder aus zwei Unterabfragen stammen, die jeweils zehn Zeilen und drei haben! Sie werden unabhängig voneinander jeweils in null Sekunden ausgeführt, und da die Zeilenzahlen so kurz sind, würde ich erwarten, dass die Verbindungszeit auch bei Verwendung von verschachtelten Schleifen trivial ist.

Irgendwelche Vermutungen, warum diese scheinbar harmlose Berechnung eine TVF vollständig auslöste, während sie als eigenständige Abfrage sehr schnell ausgeführt wurde?


Ich habe die Abfrage gepostet, aber wie Sie sehen, zeichnet sie sich auf einem Dutzend Tabellen ab, einschließlich einiger Ansichten und einer anderen TVF, sodass ich befürchte, dass sie nicht hilfreich ist. Der Teil, den ich nicht verstehe, ist, wie das Umschließen einer Abfrage in eine TVF die Laufzeit mit 750 multiplizieren kann. Dies geschieht nur, wenn ich GAAC.AvgAdCost(heute; gestern ACS.AvgClickCostwar auch ein Problem) einbeziehe, sodass die Unterabfrage den Ausführungsplan zu verlassen scheint .
Jon of All Trades

1
Ich denke, Sie müssen sich die Join-Klausel für die Unterabfragen ansehen. Wenn Sie eine viel zu viele Beziehung zwischen einer der Tabellen erhalten, erhalten Sie zehnmal mehr Datensätze, die verarbeitet werden müssen.

An einem gewissen Punkt an unserem Projekt (die viele verschachtelten Ansichten und Inline - TVFs hat), fanden wir sie zu ersetzen COALESCE()mit , ISNULL()um den Abfrage - Optimierer Entwurf bessere Pläne. Ich denke, es hat etwas mit ISNULL()einem vorhersehbareren Ausgabetyp zu tun als COALESCE(). Einen Versuch wert? Ich weiß, dass dies vage ist, aber nach unserer begrenzten Erfahrung scheint es eine unscharfe Kunst zu sein, den Abfrageoptimierer in Richtung besserer Pläne zu beeinflussen. Deshalb haben wir nur Fortschritte erzielt, wenn wir ein paar vage verrückte Ideen aus Verzweiflung ausprobieren.

2

Ich gehe davon aus, dass dies mit Parameter-Sniffing zu tun hat.

Einige Beiträge zu diesen Themen finden Sie hier (und Sie können SO nach Parameter-Sniffing durchsuchen.)

http://blogs.msdn.com/b/queryoptteam/archive/2006/03/31/565991.aspx


Bei Inline-TVFs wird kein Parameter-Sniffing durchgeführt: Es handelt sich lediglich um Makros, die sich wie Ansichten erweitern.
24.

@gbn: Es mag wahr sein, dass die TVF selbst wie ein Makro erweitert wird, aber (wie ich es verstehe) die Abfrage oder der Sproc, der letztendlich diese Erweiterung ausführt, unterliegt der Planung und möglichen Parametrisierung. (Wir haben vor einiger Zeit in SQL Server 2005 damit gekämpft. Der Kampf war besonders schwierig, bis wir herausfanden, dass SQL Server Management Studio ( ARITHABORTmöglicherweise?) Andere Sitzungseinstellungen als Reporting Services und / oder jTDS verwendet, sodass sich manchmal eine davon einfallen ließ Ein "schlechter" Plan, aber andere würden (wütend) "auf der gleichen Anfrage" in Ordnung sein.)

Es riecht nach Schnüffeln für mich ...
Hogan

Hmm, viel zu lesen. Für die parametrisierten Werte gibt es keinen großen Unterschied in der Kardinalität: Die Abfrage enthält eine Datumstabelle mit einer einzelnen Zeile pro Datum und mehrere andere Tabellen mit vielen Zeilen pro Datum, aber ungefähr der gleichen Nummer für ein bestimmtes Datum. Ich verwende die gleichen Parameter (21.05. Bis 23.05.) In einer Testausführung unmittelbar nach dem (erneuten) Erstellen der UDF. Daher sollte sie, wenn überhaupt, für diese Werte "vorbereitet" werden.
Jon of All Trades

Noch eine Anmerkung: Das Zuweisen der Parameterwerte zu lokalen Variablen, wie von Jetson in stackoverflow.com/questions/211355/… beschrieben, hatte keine wesentlichen Auswirkungen.
Jon of All Trades

1

Leider kann die Abfrageoptimierungs-Engine von SQL keine internen Funktionen erkennen.

Also würde ich den Ausführungsplan aus dem schnellen verwenden, um herauszufinden, welche Hinweise in der TF anzuwenden sind. Spülen und wiederholen, bis der Ausführungsplan des TF dem schnelleren entspricht.

http://sqlblog.com/blogs/tibor_karaszi/archive/2008/08/29/execution-plan-re-use-sp-executesql-and-tsql-variables.aspx


2
Das SQL Server-Abfrageoptimierungsprogramm kann innerhalb von ITVFs (Inline-Tabellenwertfunktionen) sehen, jedoch keine anderen.

Hinweis: Inline-Tabellenfunktionen mit Kreuz können bei korrekter Auslegung zu einer enormen Leistungssteigerung führen. Beispielsweise könnte ein nicht aufladbarer Ausdruck in einem Join wie Ihrem Coalesce in eine apply-Anweisung eingeschlossen, als Satz ausgewertet und dann in der nächsten Abfrage mit einem Join verknüpft werden, ohne dass daraus RBAR wird. Experimentiere ein wenig. Cross Apply ist schwer zu meistern, aber es lohnt sich!
SheldonH

0

Was sind die Unterschiede in diesen Werten bitte?

arithabort              1
ansi_null_dflt_on       1
ansi_defaults           0
ansi_warnings           1
ansi_padding            1
ansi_nulls              1

Es hat sich gezeigt, dass diese (insbesondere Arithabort) die Abfrageleistung auf diese Weise erheblich beeinträchtigen.


Dies liegt daran, dass es sich eher um einen Plan-Cache-Schlüssel handelt als um etwas an sich arithabortselbst, nicht wahr? Seit SQL Server 2005 dachte ich, dass diese Einstellung keine Auswirkung hat, solange sie aktiviert ansi_warningsist. (Im Jahr 2000 werden indizierte Ansichten nicht verwendet, wenn sie falsch eingestellt sind.)
Martin Smith,

@Martin: Ich habe keine direkte Erfahrung damit, erinnere mich aber, dass ich kürzlich etwas gelesen habe. Und einige SO Antworten darauf zu finden. Es kann OP helfen, es kann nicht ... Edit: sqlblog.com/blogs/kalen_delaney/archive/2008/06/19/… sigh
gbn

Ich habe ähnliche ziemlich eindeutige Behauptungen über SO gelesen. Ich habe noch nie etwas gesehen, das es mir erlaubt, es für mich selbst oder eine logische Erklärung zu reproduzieren, warum die arithabortEinstellung einen solch dramatischen Einfluss auf die Leistung haben sollte, daher bin ich im Moment ein bisschen skeptisch.
Martin Smith

ARITHABORT, ANSI_WARNINGS, ANSI_PADDING und ANSI_NULL sind 1, der Rest ist NULL.
Jon of All Trades

Zu Ihrer Information, ich arbeite komplett in SSMS, daher sind unterschiedliche Einstellungen in VS oder anderen Clients nicht in Frage.
Jon of All Trades
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.