มีการเก็บประวัติแบบสอบถามในไฟล์บันทึกบางไฟล์หรือไม่ ถ้าใช่คุณช่วยบอกวิธีการหาที่ตั้งของพวกเขาได้ไหม ถ้าไม่คุณสามารถให้คำแนะนำเกี่ยวกับวิธีการดูได้หรือไม่?
มีการเก็บประวัติแบบสอบถามในไฟล์บันทึกบางไฟล์หรือไม่ ถ้าใช่คุณช่วยบอกวิธีการหาที่ตั้งของพวกเขาได้ไหม ถ้าไม่คุณสามารถให้คำแนะนำเกี่ยวกับวิธีการดูได้หรือไม่?
คำตอบ:
[เนื่องจากคำถามนี้น่าจะถูกปิดซ้ำซ้อน]
หาก SQL Server ไม่ได้ถูกรีสตาร์ท (และแผนยังไม่ถูกขับไล่ ฯลฯ ) คุณอาจจะสามารถค้นหาแบบสอบถามในแคชแผน
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%';
หากคุณทำไฟล์หายเนื่องจาก Management Studio ขัดข้องคุณอาจพบไฟล์การกู้คืนได้ที่นี่:
C:\Users\<you>\Documents\SQL Server Management Studio\Backup Files\
ไม่เช่นนั้นคุณจะต้องใช้สิ่งอื่นในอนาคตเพื่อช่วยคุณบันทึกประวัติการสืบค้นของคุณเช่น SSMS Tools Pack ตามที่ระบุไว้ในคำตอบของ Ed Harper - แม้ว่ามันจะไม่ฟรีใน SQL Server 2012+ ก็ตาม หรือคุณสามารถตั้งค่าการติดตามการกรองน้ำหนักเบาบางส่วนในชื่อล็อกอินหรือชื่อโฮสต์ของคุณ (แต่โปรดใช้การติดตามฝั่งเซิร์ฟเวอร์ไม่ใช่ Profiler สำหรับสิ่งนี้)
ตามที่ @ Nenad-Zivkovic แสดงความคิดเห็นอาจเป็นประโยชน์ในการเข้าร่วมsys.dm_exec_query_stats
และสั่งซื้อโดย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;
sys.dm_exec_query_stats
และค้นหาหรือสั่งซื้อโดยlast_execution_time
มาช้า แต่หวังว่าจะมีประโยชน์เพราะมันจะเพิ่มรายละเอียดเพิ่มเติม ...
ไม่มีวิธีดูข้อความค้นหาที่ดำเนินการใน SSMS เป็นค่าเริ่มต้น มีหลายตัวเลือกว่า
การอ่านบันทึกธุรกรรม - นี่ไม่ใช่เรื่องง่ายที่จะทำเพราะอยู่ในรูปแบบที่เป็นกรรมสิทธิ์ อย่างไรก็ตามหากคุณต้องการดูข้อความค้นหาที่ดำเนินการในอดีต (ยกเว้น SELECT) นี่เป็นวิธีเดียวเท่านั้น
คุณสามารถใช้เครื่องมือของบุคคลที่สามสำหรับสิ่งนี้เช่นApexSQL LogและSQL Log Rescue (ฟรียกเว้น SQL 2000 เท่านั้น) ตรวจสอบหัวข้อนี้สำหรับรายละเอียดเพิ่มเติมได้ที่นี่บันทึกธุรกรรม Explorer / Analyzer ของ SQL Server
ตัวสร้างโปรไฟล์ของ SQL Server - เหมาะสมที่สุดถ้าคุณแค่ต้องการเริ่มการตรวจสอบและคุณไม่สนใจสิ่งที่เกิดขึ้นก่อนหน้านี้ ตรวจสอบให้แน่ใจว่าคุณใช้ตัวกรองเพื่อเลือกเฉพาะธุรกรรมที่คุณต้องการ มิฉะนั้นคุณจะต้องจบด้วยข้อมูลจำนวนมากอย่างรวดเร็ว
การติดตาม SQL Server - เหมาะสมที่สุดหากคุณต้องการดักจับคำสั่งทั้งหมดหรือส่วนใหญ่และเก็บไว้ในไฟล์ติดตามที่สามารถแยกวิเคราะห์ได้ในภายหลัง
ทริกเกอร์ - เหมาะสมที่สุดหากคุณต้องการจับภาพ DML (ยกเว้นเลือก) และเก็บสิ่งเหล่านี้ไว้ในฐานข้อมูล
ชุดเครื่องมือ SSMSเพิ่มฟังก์ชันการทำงานเพื่อบันทึกประวัติการใช้งานและอื่น ๆ
ดังที่คนอื่น ๆ ระบุไว้คุณสามารถใช้ SQL Profiler แต่คุณสามารถใช้ประโยชน์จากฟังก์ชันการทำงานผ่าน sp_trace_ * กระบวนงานที่เก็บไว้ในระบบ ตัวอย่างเช่นตัวอย่าง SQL นี้จะ (อย่างน้อยในปี 2000 ฉันคิดว่ามันเหมือนกันสำหรับ SQL 2008 แต่คุณจะต้องตรวจสอบอีกครั้ง) จับRPC:Completed
และSQL:BatchCompleted
กิจกรรมสำหรับการค้นหาทั้งหมดที่ใช้เวลานานกว่า 10 วินาทีในการทำงานและบันทึกผลลัพธ์ tracefile ที่คุณสามารถเปิดใน SQL profiler ได้ในภายหลัง:
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
คุณสามารถค้นหา ID สำหรับแต่ละเหตุการณ์การติดตามคอลัมน์ ฯลฯ จาก Books Online เพียงค้นหาsp_trace_create , sp_trace_seteventและsp_trace_setfiler sprocs จากนั้นคุณสามารถควบคุมการติดตามได้ดังนี้:
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
... โดยที่ '15' คือ ID การติดตาม (ตามที่รายงานโดย sp_trace_create ซึ่งสคริปต์แรกเริ่มต้นเหนือ)
คุณสามารถตรวจสอบว่ามีร่องรอยใดบ้างที่ทำงานอยู่:
select * from ::fn_trace_getinfo(default)
สิ่งเดียวที่ฉันจะพูดด้วยความระมัดระวัง - ฉันไม่รู้ว่าจะโหลดระบบของคุณมากแค่ไหน มันจะเพิ่มบางอย่าง แต่ขนาดของ "บางอย่าง" นั้นอาจขึ้นอยู่กับว่าเซิร์ฟเวอร์ของคุณยุ่งแค่ไหน
ระบบจะไม่บันทึกข้อความค้นหาด้วยวิธีดังกล่าว ถ้าคุณรู้ว่าคุณต้องการทำสิ่งนั้นล่วงหน้าคุณสามารถใช้ SQL Profiler เพื่อบันทึกสิ่งที่กำลังเกิดขึ้นและติดตามแบบสอบถามในระหว่างที่ Profiler ทำงานอยู่
ฉันใช้แบบสอบถามด้านล่างสำหรับการติดตามกิจกรรมแอปพลิเคชันบนเซิร์ฟเวอร์ SQL ที่ไม่ได้เปิดใช้งานตัวติดตามโปรไฟล์ วิธีนี้ใช้ Query Store (SQL Server 2016+) แทน DMV สิ่งนี้ให้ความสามารถที่ดีกว่าในการดูข้อมูลเชิงประวัติเช่นเดียวกับการค้นหาที่เร็วขึ้น มันมีประสิทธิภาพมากในการดักจับคิวรีที่เรียกใช้ระยะสั้นที่ไม่สามารถดักจับโดย sp_who / sp_whoisactive
/* 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())
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
สิ่งนี้จะแสดงเวลาและวันที่ของคุณเมื่อมีการเรียกใช้แบบสอบถาม
คุณสามารถตรวจสอบแบบสอบถามSQLโดยSQL Profilerหากคุณต้องการ
สามารถดูประวัติแบบสอบถามโดยใช้มุมมองระบบ:
ตัวอย่างเช่นการใช้แบบสอบถามต่อไปนี้:
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%'
คิวรี่ที่กำลังรันอยู่สามารถดูได้โดยใช้สคริปต์ต่อไปนี้:
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])
คำขอนี้แสดงคำขอที่ใช้งานทั้งหมดและขอทุกคนที่ชัดเจนป้องกันคำขอที่ใช้งาน
สคริปต์เหล่านี้และสคริปต์ที่เป็นประโยชน์อื่น ๆ ทั้งหมดได้รับการติดตั้งเพื่อเป็นตัวแทนใน ฐานข้อมูลSRVซึ่งแจกจ่ายได้อย่างอิสระ ยกตัวอย่างเช่นสคริปต์แรกที่มาจากมุมมอง[INF]. [vBigQuery]และที่สองมาจากมุมมอง[INF]. [vRequests]
นอกจากนี้ยังมีโซลูชันบุคคลที่สามที่หลากหลายสำหรับประวัติแบบสอบถาม ฉันใช้Query ManagerจากDbeaver : และQuery Execution Historyจากเครื่องมือ SQLซึ่งฝังอยู่ในSSMS :
คุณลักษณะนี้ไม่มีอยู่ในกล่องใน SSMS
หากคุณกำลังใช้ SSMS 18 หรือใหม่กว่าคุณอาจต้องการลอง SSMSPlus
มันมีคุณสมบัติประวัติแบบสอบถาม
https://github.com/akarzazi/SSMSPlus
คำเตือน: ฉันเป็นผู้เขียน
คุณสามารถใช้ "สร้างสคริปต์อัตโนมัติทุกครั้งที่บันทึก" หากคุณใช้สตูดิโอจัดการ นี่ไม่ใช่การบันทึกอย่างแน่นอน ตรวจสอบว่ามีประโยชน์สำหรับคุณ .. ;)
หากเคียวรีที่คุณสนใจเป็นคิวรีแบบไดนามิกที่ล้มเหลวเป็นระยะ ๆ คุณสามารถบันทึก SQL และวันที่และเวลาและผู้ใช้ในตารางในเวลาที่มีการสร้างคำสั่งแบบไดนามิก มันจะดำเนินการเป็นกรณี ๆ ไปเนื่องจากจำเป็นต้องมีการเขียนโปรแกรมเฉพาะและต้องใช้เวลาในการประมวลผลเพิ่มเติมเล็กน้อยดังนั้นให้ทำเฉพาะกับแบบสอบถามที่คุณกังวลมากที่สุดเท่านั้น แต่การมีบันทึกของข้อความเฉพาะที่ดำเนินการสามารถช่วยได้จริง ๆ เมื่อคุณพยายามหาสาเหตุว่าทำไมมันล้มเหลวเดือนละครั้งเท่านั้น การสืบค้นแบบไดนามิกนั้นยากที่จะทดสอบอย่างละเอียดและบางครั้งคุณจะได้รับค่าอินพุตหนึ่งค่าที่ไม่สามารถใช้งานได้และการทำบันทึกนี้ในเวลาที่ SQL ถูกสร้างมักจะเป็นวิธีที่ดีที่สุดในการดูว่าอะไรเป็นพิเศษใน SQL ที่สร้างขึ้น
วิธีการที่ไม่เหมาะสมในกล่องเล็กน้อยคือการเขียนสคริปต์โซลูชันใน AutoHotKey ฉันใช้สิ่งนี้และมันไม่สมบูรณ์แบบ แต่ใช้ได้ดีและฟรี โดยพื้นฐานแล้วสคริปต์นี้จะกำหนดฮอตคีย์ให้กับCTRL+ SHIFT+ Rซึ่งจะคัดลอก SQL ที่เลือกใน SSMS ( CTRL+ C), บันทึกไฟล์ datestamp SQL จากนั้นเรียกใช้คิวรีที่เน้น ( F5) หากคุณไม่คุ้นเคยกับสคริปต์ AHK เซมิโคลอนชั้นนำจะเป็นความคิดเห็น
;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
ข้อ จำกัด ที่ใหญ่ที่สุดคือสคริปต์นี้จะไม่ทำงานหากคุณคลิก "ดำเนินการ" แทนที่จะใช้แป้นพิมพ์ลัดและสคริปต์นี้จะไม่บันทึกไฟล์ทั้งหมด - เพียงแค่ข้อความที่เลือก แต่คุณสามารถแก้ไขสคริปต์เพื่อเรียกใช้คิวรี่ได้ตลอดเวลาจากนั้นเลือกทั้งหมด ( CTRL+A ) หน้าคัดลอก / บันทึก
การใช้เครื่องมือแก้ไขที่ทันสมัยพร้อมคุณสมบัติ "ค้นหาในไฟล์" จะช่วยให้คุณค้นหาประวัติ SQL ของคุณ คุณสามารถได้รับแฟนซีและขูดไฟล์ของคุณลงในฐานข้อมูล SQLite3 เพื่อสอบถามแบบสอบถามของคุณ