Anzeigen des Abfrageverlaufs in SQL Server Management Studio

159

Wird der Abfrageverlauf in einigen Protokolldateien gespeichert? Wenn ja, können Sie mir sagen, wie ich ihren Standort finde? Wenn nicht, können Sie mir einen Rat geben, wie ich es sehen kann?

mstaniloiu
quelle
1
http://www.ssmstoolspack.com/ bietet ein Verlaufsfenster, wenn Sie danach suchen.
TI

Antworten:

226

[Da diese Frage wahrscheinlich als Duplikat geschlossen wird.]

Wenn SQL Server nicht neu gestartet wurde (und der Plan nicht entfernt wurde usw.), können Sie die Abfrage möglicherweise im Plan-Cache finden.

SELECT t.[text]
FROM sys.dm_exec_cached_plans AS p
CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) AS t
WHERE t.[text] LIKE N'%something unique about your query%';

Wenn Sie die Datei verloren haben, weil Management Studio abgestürzt ist, können Sie möglicherweise Wiederherstellungsdateien hier finden:

C:\Users\<you>\Documents\SQL Server Management Studio\Backup Files\

Andernfalls müssen Sie in Zukunft etwas anderes verwenden, um Ihren Abfrageverlauf zu speichern, z. B. SSMS Tools Pack, wie in der Antwort von Ed Harper erwähnt - obwohl es in SQL Server 2012+ nicht kostenlos ist. Sie können auch eine einfache Ablaufverfolgung einrichten, die nach Ihrem Anmelde- oder Hostnamen gefiltert ist (verwenden Sie hierfür jedoch eine serverseitige Ablaufverfolgung, nicht Profiler).


Wie @ Nenad-Zivkovic kommentierte, könnte es hilfreich sein, mitzumachen sys.dm_exec_query_statsund zu bestellen bei last_execution_time:

SELECT t.[text], s.last_execution_time
FROM sys.dm_exec_cached_plans AS p
INNER JOIN sys.dm_exec_query_stats AS s
   ON p.plan_handle = s.plan_handle
CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) AS t
WHERE t.[text] LIKE N'%something unique about your query%'
ORDER BY s.last_execution_time DESC;
Aaron Bertrand
quelle
9
Könnte auch helfen, mitzumachen sys.dm_exec_query_statsund zu suchen oder zu bestellen vonlast_execution_time
Nenad Zivkovic
Funktioniert nicht mit SQL Server 2000 und funktioniert mit SQL Server 2005
Durai Amuthan.H
@Duraiamuthan Nun, die Frage stellt sich nach Management Studio, daher sollte es sicher sein, 2005+ anzunehmen. 2000 hatte kein Management Studio, es hatte Query Analyzer. 2000 ist auch viele Jahre ohne Unterstützung. Wenn Sie dieses Problem für SQL Server 2000 lösen möchten, sollten Sie wahrscheinlich eine neue Frage stellen, die mit dieser bestimmten Version gekennzeichnet ist (wenn kein Duplikat vorhanden ist, das ich nicht überprüft habe).
Aaron Bertrand
1
@ AaronBertrand Mein Kommentar ist eine Ergänzung zu Ihrer Antwort. Es wird anderen helfen
Durai Amuthan.H
3
@ AaronBertrand Du bist ein Gott unter den Menschen.
AnotherDeveloper
49

Spät, aber hoffentlich nützlich, da es mehr Details hinzufügt ...

Abfragen können standardmäßig nicht in SSMS ausgeführt werden. Es gibt jedoch mehrere Möglichkeiten.

Transaktionsprotokoll lesen - dies ist nicht einfach, da es im proprietären Format vorliegt. Wenn Sie jedoch Abfragen anzeigen müssen, die historisch ausgeführt wurden (außer SELECT), ist dies der einzige Weg.

Sie können hierfür Tools von Drittanbietern wie ApexSQL Log und SQL Log Rescue verwenden (kostenlos, aber nur SQL 2000). Weitere Informationen finden Sie in diesem Thread hier. SQL Server Transaction Log Explorer / Analyzer

SQL Server-Profiler - am besten geeignet, wenn Sie nur mit der Überwachung beginnen möchten und nicht daran interessiert sind, was früher passiert ist. Stellen Sie sicher, dass Sie Filter verwenden, um nur die Transaktionen auszuwählen, die Sie benötigen. Andernfalls erhalten Sie sehr schnell eine Menge Daten.

SQL Server-Ablaufverfolgung - am besten geeignet, wenn Sie alle oder die meisten Befehle erfassen und in einer Ablaufverfolgungsdatei speichern möchten, die später analysiert werden kann.

Trigger - am besten geeignet, wenn Sie DML erfassen (außer auswählen) und diese irgendwo in der Datenbank speichern möchten

Djordje Kujundzic
quelle
Das Erstellen einer Trace-Datei im SQL Server-Profiler ( msdn.microsoft.com/en-us/library/ms175047(v=sql.110).aspx ) mithilfe der Standardvorlage ist eine gute Möglichkeit, um ausgeführte Anweisungen zu überwachen.
javiniar.leonard
16

Das SSMS-Tools Pack bietet unter anderem Funktionen zum Aufzeichnen des Ausführungsverlaufs.

Ed Harper
quelle
22
Ab SSMS 2012 ist es nicht mehr kostenlos.
mattmc3
6

Wie andere angemerkt haben, können Sie SQL Profiler verwenden, aber Sie können seine Funktionalität auch über gespeicherte Systemprozeduren sp_trace_ * nutzen. Zum Beispiel wird dieses SQL-Snippet (zumindest für 2000; ich denke, es ist dasselbe für SQL 2008, aber Sie müssen es noch einmal überprüfen) abfangen RPC:Completedund SQL:BatchCompletedEreignisse für alle Abfragen, deren Ausführung länger als 10 Sekunden dauert, und die Ausgabe in speichern Eine Trace-Datei, die Sie zu einem späteren Zeitpunkt im SQL-Profiler öffnen können:

DECLARE @TraceID INT
DECLARE @ON BIT
DECLARE @RetVal INT
SET @ON = 1

exec @RetVal = sp_trace_create @TraceID OUTPUT, 2, N'Y:\TraceFile.trc'
print 'This trace is Trace ID = ' + CAST(@TraceID AS NVARCHAR)
print 'Return value = ' + CAST(@RetVal AS NVARCHAR)
-- 10 = RPC:Completed
exec sp_trace_setevent @TraceID, 10, 1, @ON     -- Textdata
exec sp_trace_setevent @TraceID, 10, 3, @ON     -- DatabaseID
exec sp_trace_setevent @TraceID, 10, 12, @ON        -- SPID
exec sp_trace_setevent @TraceID, 10, 13, @ON        -- Duration
exec sp_trace_setevent @TraceID, 10, 14, @ON        -- StartTime
exec sp_trace_setevent @TraceID, 10, 15, @ON        -- EndTime

-- 12 = SQL:BatchCompleted
exec sp_trace_setevent @TraceID, 12, 1, @ON     -- Textdata
exec sp_trace_setevent @TraceID, 12, 3, @ON     -- DatabaseID
exec sp_trace_setevent @TraceID, 12, 12, @ON        -- SPID
exec sp_trace_setevent @TraceID, 12, 13, @ON        -- Duration
exec sp_trace_setevent @TraceID, 12, 14, @ON        -- StartTime
exec sp_trace_setevent @TraceID, 12, 15, @ON        -- EndTime

-- Filter for duration [column 13] greater than [operation 2] 10 seconds (= 10,000ms)
declare @duration bigint
set @duration = 10000
exec sp_trace_setfilter @TraceID, 13, 0, 2, @duration

Die ID für jedes Ablaufverfolgungsereignis, jede Spalte usw. finden Sie in Books Online. Suche nur für die sp_trace_create , sp_trace_setevent und sp_trace_setfiler sprocs. Sie können den Trace dann wie folgt steuern:

exec sp_trace_setstatus 15, 0       -- Stop the trace
exec sp_trace_setstatus 15, 1       -- Start the trace
exec sp_trace_setstatus 15, 2       -- Close the trace file and delete the trace settings

... wobei '15' die Trace-ID ist (wie von sp_trace_create gemeldet, das das erste Skript oben auslöst).

Sie können überprüfen, mit welchen Traces ausgeführt wird:

select * from ::fn_trace_getinfo(default)

Das einzige, was ich zur Vorsicht sagen werde - ich weiß nicht, wie viel Last dies auf Ihr System ausüben wird; Es werden einige hinzugefügt, aber wie groß diese "einige" sind, hängt wahrscheinlich davon ab, wie beschäftigt Ihr Server ist.

Chris J.
quelle
Hilfreicher Code. Es hat bei mir nur funktioniert, als ich die Dateierweiterung ".trc" entfernt habe.
Steve Smith
5

Das System zeichnet keine Abfragen auf diese Weise auf. Wenn Sie jedoch wissen, dass Sie dies im Voraus tun möchten, können Sie mit SQL Profiler aufzeichnen, was eingeht, und Abfragen während der Ausführung von Profiler verfolgen.

Thyamin
quelle
5

Ich verwende die folgende Abfrage zum Verfolgen der Anwendungsaktivität auf einem SQL Server, auf dem der Ablaufverfolgungsprofiler nicht aktiviert ist. Die Methode verwendet den Abfragespeicher (SQL Server 2016+) anstelle der DMVs. Dies bietet eine bessere Möglichkeit, historische Daten einzusehen, sowie eine schnellere Suche. Es ist sehr effizient, kurzfristige Abfragen zu erfassen, die von sp_who / sp_whoisactive nicht erfasst werden können.

/* Adjust script to your needs.
    Run full script (F5) -> Interact with UI -> Run full script again (F5)
    Output will contain the queries completed in that timeframe.
*/

/* Requires Query Store to be enabled:
    ALTER DATABASE <db> SET QUERY_STORE = ON
    ALTER DATABASE <db> SET QUERY_STORE (OPERATION_MODE = READ_WRITE, MAX_STORAGE_SIZE_MB = 100000)
*/

USE <db> /* Select your DB */

IF OBJECT_ID('tempdb..#lastendtime') IS NULL
    SELECT GETUTCDATE() AS dt INTO #lastendtime
ELSE IF NOT EXISTS (SELECT * FROM #lastendtime)
    INSERT INTO #lastendtime VALUES (GETUTCDATE()) 

;WITH T AS (
SELECT 
    DB_NAME() AS DBName
    , s.name + '.' + o.name AS ObjectName
    , qt.query_sql_text
    , rs.runtime_stats_id
    , p.query_id
    , p.plan_id
    , CAST(p.last_execution_time AS DATETIME) AS last_execution_time
    , CASE WHEN p.last_execution_time > #lastendtime.dt THEN 'X' ELSE '' END AS New
    , CAST(rs.last_duration / 1.0e6 AS DECIMAL(9,3)) last_duration_s
    , rs.count_executions
    , rs.last_rowcount
    , rs.last_logical_io_reads
    , rs.last_physical_io_reads
    , q.query_parameterization_type_desc
FROM (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY plan_id, runtime_stats_id ORDER BY runtime_stats_id DESC) AS recent_stats_in_current_priod
    FROM sys.query_store_runtime_stats 
    ) AS rs
INNER JOIN sys.query_store_runtime_stats_interval AS rsi ON rsi.runtime_stats_interval_id = rs.runtime_stats_interval_id
INNER JOIN sys.query_store_plan AS p ON p.plan_id = rs.plan_id
INNER JOIN sys.query_store_query AS q ON q.query_id = p.query_id
INNER JOIN sys.query_store_query_text AS qt ON qt.query_text_id = q.query_text_id
LEFT OUTER JOIN sys.objects AS o ON o.object_id = q.object_id
LEFT OUTER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
CROSS APPLY #lastendtime
WHERE rsi.start_time <= GETUTCDATE() AND GETUTCDATE() < rsi.end_time
    AND recent_stats_in_current_priod = 1
    /* Adjust your filters: */
    -- AND (s.name IN ('<myschema>') OR s.name IS NULL)
UNION
SELECT NULL,NULL,NULL,NULL,NULL,NULL,dt,NULL,NULL,NULL,NULL,NULL,NULL, NULL
FROM #lastendtime
)
SELECT * FROM T
WHERE T.query_sql_text IS NULL OR T.query_sql_text NOT LIKE '%#lastendtime%' -- do not show myself
ORDER BY last_execution_time DESC

TRUNCATE TABLE #lastendtime
INSERT INTO #lastendtime VALUES (GETUTCDATE()) 
Martin Thøgersen
quelle
4
SELECT deqs.last_execution_time AS [Time], dest.text AS [Query], dest.*
FROM sys.dm_exec_query_stats AS deqs
CROSS APPLY sys.dm_exec_sql_text(deqs.sql_handle) AS dest
WHERE dest.dbid = DB_ID('msdb')
ORDER BY deqs.last_execution_time DESC

Dies sollte Ihnen die Uhrzeit und das Datum anzeigen, an dem eine Abfrage ausgeführt wurde

Jose Ortiz
quelle
3

Sie können SQL-Abfragen bei Bedarf mit SQL Profiler überwachen

Arsen Mkrtchyan
quelle
2

Der Abfrageverlauf kann mithilfe der Systemansichten angezeigt werden:

  1. sys.dm_exec_query_stats
  2. sys.dm_exec_sql_text
  3. sys.dm_exec_query_plan

Verwenden Sie beispielsweise die folgende Abfrage:

select  top(100)
        creation_time,
        last_execution_time,
        execution_count,
        total_worker_time/1000 as CPU,
        convert(money, (total_worker_time))/(execution_count*1000)as [AvgCPUTime],
        qs.total_elapsed_time/1000 as TotDuration,
        convert(money, (qs.total_elapsed_time))/(execution_count*1000)as [AvgDur],
        total_logical_reads as [Reads],
        total_logical_writes as [Writes],
        total_logical_reads+total_logical_writes as [AggIO],
        convert(money, (total_logical_reads+total_logical_writes)/(execution_count + 0.0)) as [AvgIO],
        [sql_handle],
        plan_handle,
        statement_start_offset,
        statement_end_offset,
        plan_generation_num,
        total_physical_reads,
        convert(money, total_physical_reads/(execution_count + 0.0)) as [AvgIOPhysicalReads],
        convert(money, total_logical_reads/(execution_count + 0.0)) as [AvgIOLogicalReads],
        convert(money, total_logical_writes/(execution_count + 0.0)) as [AvgIOLogicalWrites],
        query_hash,
        query_plan_hash,
        total_rows,
        convert(money, total_rows/(execution_count + 0.0)) as [AvgRows],
        total_dop,
        convert(money, total_dop/(execution_count + 0.0)) as [AvgDop],
        total_grant_kb,
        convert(money, total_grant_kb/(execution_count + 0.0)) as [AvgGrantKb],
        total_used_grant_kb,
        convert(money, total_used_grant_kb/(execution_count + 0.0)) as [AvgUsedGrantKb],
        total_ideal_grant_kb,
        convert(money, total_ideal_grant_kb/(execution_count + 0.0)) as [AvgIdealGrantKb],
        total_reserved_threads,
        convert(money, total_reserved_threads/(execution_count + 0.0)) as [AvgReservedThreads],
        total_used_threads,
        convert(money, total_used_threads/(execution_count + 0.0)) as [AvgUsedThreads],
        case 
            when sql_handle IS NULL then ' '
            else(substring(st.text,(qs.statement_start_offset+2)/2,(
                case
                    when qs.statement_end_offset =-1 then len(convert(nvarchar(MAX),st.text))*2      
                    else qs.statement_end_offset    
                end - qs.statement_start_offset)/2  ))
        end as query_text,
        db_name(st.dbid) as database_name,
        object_schema_name(st.objectid, st.dbid)+'.'+object_name(st.objectid, st.dbid) as [object_name],
        sp.[query_plan]
from sys.dm_exec_query_stats as qs with(readuncommitted)
cross apply sys.dm_exec_sql_text(qs.[sql_handle]) as st
cross apply sys.dm_exec_query_plan(qs.[plan_handle]) as sp
WHERE st.[text] LIKE '%query%'

Aktuelle laufende Abfragen können mithilfe des folgenden Skripts angezeigt werden:

select ES.[session_id]
      ,ER.[blocking_session_id]
      ,ER.[request_id]
      ,ER.[start_time]
      ,DateDiff(second, ER.[start_time], GetDate()) as [date_diffSec]
      , COALESCE(
                    CAST(NULLIF(ER.[total_elapsed_time] / 1000, 0) as BIGINT)
                   ,CASE WHEN (ES.[status] <> 'running' and isnull(ER.[status], '')  <> 'running') 
                            THEN  DATEDIFF(ss,0,getdate() - nullif(ES.[last_request_end_time], '1900-01-01T00:00:00.000'))
                    END
                ) as [total_time, sec]
      , CAST(NULLIF((CAST(ER.[total_elapsed_time] as BIGINT) - CAST(ER.[wait_time] AS BIGINT)) / 1000, 0 ) as bigint) as [work_time, sec]
      , CASE WHEN (ER.[status] <> 'running' AND ISNULL(ER.[status],'') <> 'running') 
                THEN  DATEDIFF(ss,0,getdate() - nullif(ES.[last_request_end_time], '1900-01-01T00:00:00.000'))
        END as [sleep_time, sec] --Время сна в сек
      , NULLIF( CAST((ER.[logical_reads] + ER.[writes]) * 8 / 1024 as numeric(38,2)), 0) as [IO, MB]
      , CASE  ER.transaction_isolation_level
        WHEN 0 THEN 'Unspecified'
        WHEN 1 THEN 'ReadUncommited'
        WHEN 2 THEN 'ReadCommited'
        WHEN 3 THEN 'Repetable'
        WHEN 4 THEN 'Serializable'
        WHEN 5 THEN 'Snapshot'
        END as [transaction_isolation_level_desc]
      ,ER.[status]
      ,ES.[status] as [status_session]
      ,ER.[command]
      ,ER.[percent_complete]
      ,DB_Name(coalesce(ER.[database_id], ES.[database_id])) as [DBName]
      , SUBSTRING(
                    (select top(1) [text] from sys.dm_exec_sql_text(ER.[sql_handle]))
                  , ER.[statement_start_offset]/2+1
                  , (
                        CASE WHEN ((ER.[statement_start_offset]<0) OR (ER.[statement_end_offset]<0))
                                THEN DATALENGTH ((select top(1) [text] from sys.dm_exec_sql_text(ER.[sql_handle])))
                             ELSE ER.[statement_end_offset]
                        END
                        - ER.[statement_start_offset]
                    )/2 +1
                 ) as [CURRENT_REQUEST]
      ,(select top(1) [text] from sys.dm_exec_sql_text(ER.[sql_handle])) as [TSQL]
      ,(select top(1) [objectid] from sys.dm_exec_sql_text(ER.[sql_handle])) as [objectid]
      ,(select top(1) [query_plan] from sys.dm_exec_query_plan(ER.[plan_handle])) as [QueryPlan]
      ,NULL as [event_info]--(select top(1) [event_info] from sys.dm_exec_input_buffer(ES.[session_id], ER.[request_id])) as [event_info]
      ,ER.[wait_type]
      ,ES.[login_time]
      ,ES.[host_name]
      ,ES.[program_name]
      ,cast(ER.[wait_time]/1000 as decimal(18,3)) as [wait_timeSec]
      ,ER.[wait_time]
      ,ER.[last_wait_type]
      ,ER.[wait_resource]
      ,ER.[open_transaction_count]
      ,ER.[open_resultset_count]
      ,ER.[transaction_id]
      ,ER.[context_info]
      ,ER.[estimated_completion_time]
      ,ER.[cpu_time]
      ,ER.[total_elapsed_time]
      ,ER.[scheduler_id]
      ,ER.[task_address]
      ,ER.[reads]
      ,ER.[writes]
      ,ER.[logical_reads]
      ,ER.[text_size]
      ,ER.[language]
      ,ER.[date_format]
      ,ER.[date_first]
      ,ER.[quoted_identifier]
      ,ER.[arithabort]
      ,ER.[ansi_null_dflt_on]
      ,ER.[ansi_defaults]
      ,ER.[ansi_warnings]
      ,ER.[ansi_padding]
      ,ER.[ansi_nulls]
      ,ER.[concat_null_yields_null]
      ,ER.[transaction_isolation_level]
      ,ER.[lock_timeout]
      ,ER.[deadlock_priority]
      ,ER.[row_count]
      ,ER.[prev_error]
      ,ER.[nest_level]
      ,ER.[granted_query_memory]
      ,ER.[executing_managed_code]
      ,ER.[group_id]
      ,ER.[query_hash]
      ,ER.[query_plan_hash]
      ,EC.[most_recent_session_id]
      ,EC.[connect_time]
      ,EC.[net_transport]
      ,EC.[protocol_type]
      ,EC.[protocol_version]
      ,EC.[endpoint_id]
      ,EC.[encrypt_option]
      ,EC.[auth_scheme]
      ,EC.[node_affinity]
      ,EC.[num_reads]
      ,EC.[num_writes]
      ,EC.[last_read]
      ,EC.[last_write]
      ,EC.[net_packet_size]
      ,EC.[client_net_address]
      ,EC.[client_tcp_port]
      ,EC.[local_net_address]
      ,EC.[local_tcp_port]
      ,EC.[parent_connection_id]
      ,EC.[most_recent_sql_handle]
      ,ES.[host_process_id]
      ,ES.[client_version]
      ,ES.[client_interface_name]
      ,ES.[security_id]
      ,ES.[login_name]
      ,ES.[nt_domain]
      ,ES.[nt_user_name]
      ,ES.[memory_usage]
      ,ES.[total_scheduled_time]
      ,ES.[last_request_start_time]
      ,ES.[last_request_end_time]
      ,ES.[is_user_process]
      ,ES.[original_security_id]
      ,ES.[original_login_name]
      ,ES.[last_successful_logon]
      ,ES.[last_unsuccessful_logon]
      ,ES.[unsuccessful_logons]
      ,ES.[authenticating_database_id]
      ,ER.[sql_handle]
      ,ER.[statement_start_offset]
      ,ER.[statement_end_offset]
      ,ER.[plan_handle]
      ,NULL as [dop]--ER.[dop]
      ,coalesce(ER.[database_id], ES.[database_id]) as [database_id]
      ,ER.[user_id]
      ,ER.[connection_id]
from sys.dm_exec_requests ER with(readuncommitted)
right join sys.dm_exec_sessions ES with(readuncommitted)
on ES.session_id = ER.session_id 
left join sys.dm_exec_connections EC  with(readuncommitted)
on EC.session_id = ES.session_id
where ER.[status] in ('suspended', 'running', 'runnable')
or exists (select top(1) 1 from sys.dm_exec_requests as ER0 where ER0.[blocking_session_id]=ES.[session_id])

Diese Anforderung zeigt alle aktiven Anforderungen und alle Anforderungen an, die aktive Anforderungen explizit blockieren.

Alle diese und andere nützliche Skripte werden als Darstellungen in der SRV- Datenbank implementiert , die frei verteilt wird. Das erste Skript stammt beispielsweise aus der Ansicht [inf]. [VBigQuery] und das zweite aus der Ansicht [inf]. [VRequests] .

Es gibt auch verschiedene Lösungen von Drittanbietern für den Abfrageverlauf. Ich verwende Query Manager von Dbeaver : Geben Sie hier die Bildbeschreibung ein und Query Execution History von SQL Tools , das in SSMS eingebettet ist : Geben Sie hier die Bildbeschreibung ein

Evgeniy Gribkov
quelle
1

Diese Funktion ist in SSMS nicht sofort verfügbar.

Wenn Sie SSMS 18 oder höher verwenden, können Sie SSMSPlus ausprobieren.

Es verfügt über eine Abfrageverlaufsfunktion.

https://github.com/akarzazi/SSMSPlus

Haftungsausschluss: Ich bin der Autor.

Adelos
quelle
0

Sie können "Skript bei jedem Speichern automatisch generieren" verwenden, wenn Sie Management Studio verwenden. Dies ist nicht sicher Protokollierung. Überprüfen Sie, ob es für Sie nützlich ist ..;)

Sünde
quelle
0

Wenn es sich bei den Abfragen, an denen Sie interessiert sind, um dynamische Abfragen handelt, die zeitweise fehlschlagen, können Sie SQL sowie Datum und Uhrzeit und Benutzer zum Zeitpunkt der Erstellung der dynamischen Anweisung in einer Tabelle protokollieren. Dies würde jedoch von Fall zu Fall erfolgen, da eine spezifische Programmierung erforderlich ist und ein wenig zusätzliche Verarbeitungszeit erforderlich ist. Tun Sie dies also nur für die wenigen Abfragen, die Sie am meisten interessieren. Ein Protokoll der spezifischen Anweisungen kann jedoch hilfreich sein, wenn Sie herausfinden möchten, warum dies nur einmal im Monat fehlschlägt. Dynamische Abfragen sind schwer gründlich zu testen, und manchmal erhalten Sie einen bestimmten Eingabewert, der einfach nicht funktioniert. Diese Protokollierung zum Zeitpunkt der SQL-Erstellung ist häufig der beste Weg, um festzustellen, was speziell in der erstellten SQL nicht vorhanden war.

HLGEM
quelle
0

Eine etwas unkonventionelle Methode wäre das Skripten einer Lösung in AutoHotKey. Ich benutze dies und es ist nicht perfekt, aber es funktioniert und ist kostenlos. Im Wesentlichen weist dieses Skript CTRL+ SHIFT+ einen Hotkey zu, Rder das ausgewählte SQL in SSMS ( CTRL+ C) kopiert , eine Datenstempel-SQL-Datei speichert und dann die hervorgehobene Abfrage ( F5) ausführt . Wenn Sie nicht an AHK-Skripte gewöhnt sind, ist das führende Semikolon ein Kommentar.

;CTRL+SHIFT+R to run a query that is first saved off
^+r::
;Copy
Send, ^c
; Set variables
EnvGet, HomeDir, USERPROFILE
FormatTime, DateString,,yyyyMMdd
FormatTime, TimeString,,hhmmss
; Make a spot to save the clipboard
FileCreateDir %HomeDir%\Documents\sqlhist\%DateString%
FileAppend, %Clipboard%, %HomeDir%\Documents\sqlhist\%DateString%\%TimeString%.sql
; execute the query
Send, {f5}
Return

Die größten Einschränkungen bestehen darin, dass dieses Skript nicht funktioniert, wenn Sie auf "Ausführen" klicken, anstatt die Tastenkombination zu verwenden, und dieses Skript nicht die gesamte Datei - nur den ausgewählten Text - speichert. Sie können das Skript jedoch jederzeit ändern, um die Abfrage auszuführen, und dann vor dem Kopieren / Speichern alle ( CTRL+ A) auswählen .

Mit einem modernen Editor mit Funktionen zum Suchen in Dateien können Sie Ihren SQL-Verlauf durchsuchen. Sie könnten sogar Lust bekommen und Ihre Dateien in eine SQLite3-Datenbank kratzen, um Ihre Abfragen abzufragen.

mattmc3
quelle