আপনি যখন বলেন, "ট্রিগার ব্যবহার না করে", আপনি কি টেবিলগুলিতে কোনও ট্রিগার বা সারি সারি সারি ট্রিগার বলতে চাইছেন ?
আমি জিজ্ঞাসা কারণ আপনার পারে তুমি কি বিচক্ষণ ব্যবহারের সঙ্গে চান পেতে সক্ষম হবেন CONTEXT_INFO()
ফাংশন, কিন্তু আপনি তা নিশ্চিত করার জন্য প্রয়োজন হবে SET CONTEXT_INFO
বলা হয় সঠিকভাবে করার আগে আপনার অপারেশন ঘটে।
এটি করার একটি জায়গা হ'ল সার্ভার-লেভেল লগন ট্রিগার (যেমন কোনও ডাটাবেস / অবজেক্ট-স্তরের ট্রিগার নয়) হতে পারে:
USE master
GO
CREATE TRIGGER tr_audit_login
ON ALL SERVER
WITH EXECUTE AS 'sa'
AFTER LOGON
AS BEGIN
BEGIN TRY
DECLARE @eventdata XML = EVENTDATA();
IF @eventdata IS NOT NULL BEGIN
DECLARE @spid INT;
DECLARE @client_host VARCHAR(64);
SET @client_host = @eventdata.value('(/EVENT_INSTANCE/ClientHost)[1]', 'VARCHAR(64)');
SET @spid = @eventdata.value('(/EVENT_INSTANCE/SPID)[1]', 'INT');
-- pack the required data into the context data binary
-- (spid is just an example of packing multiple data items in a single field: you would probably use @@SPID at the point of use, instead)
DECLARE @context_data VARBINARY(128);
SET @context_data = CONVERT(VARBINARY(4), @spid)
+ CONVERT(VARBINARY(64), @client_host);
-- persist the spid and host into session-level memory
SET CONTEXT_INFO @context_data;
END
END TRY
BEGIN CATCH
/* do better error handling here...
* logon trigger can lock all users out of server, so i am just swallowing everything
*/
DECLARE @msg NVARCHAR(4000) = ERROR_MESSAGE();
RAISERROR('%s', 10, 1, @msg) WITH LOG;
END CATCH
END
এরপরে আপনি আপনার সারণীতে ডিফল্ট সীমাবদ্ধতা যুক্ত করতে পারেন, প্রসঙ্গ সংরক্ষণ করতে (সন্নিবেশের গতির জন্য):
ALTER TABLE cdc.schema_table_CT
ADD ContextInfo varbinary(128) NULL DEFAULT(CONTEXT_INFO())
আপনার কাছে একবার হয়ে গেলে আপনি ContextInfo
কলামটি কিছুটা স্লাইস-ডাইস দিয়ে জিজ্ঞাসা করতে পারেন :
SELECT *
,spid = CONVERT(INT, SUBSTRING(ContextInfo, 1, 4))
,client = CONVERT(VARCHAR(64), SUBSTRING(ContextInfo, 5, 64))
FROM cdc.schema_table_CT
প্রযুক্তিগতভাবে, আপনি এটি করতে পারবেন SUBSTRING
এবং CONVERT
আপনার ডিফল্ট সীমাবদ্ধতার অংশ হিসাবে স্টাফ করতে পারবেন এবং ক্লায়েন্টের আইপি কেবল সেখানে সংরক্ষণ করতে পারেন তবে পুরো প্রেক্ষাপটটি সেখানে সংরক্ষণ করা তত দ্রুত হতে পারে (এটি প্রতিটি হিসাবে করা হয় INSERT
) এবং কেবলমাত্র মানগুলিতে একটিটি বের করতে পারেন SELECT
যখন আপনি তাদের প্রয়োজন।
আমি আমার সমস্ত SUBSTRING
এবং CONVERT
কলগুলিকে একটি একক-সারি ইনলাইন টেবিল-মূল্যবান ফাংশনটিতে গুটিয়ে রাখতে আগ্রহী হতে পারি , যা CROSS APPLY
যখন প্রয়োজন হয় আমি চাই । এটি আনপ্যাকিং যুক্তি এক জায়গায় রাখে:
CREATE FUNCTION fn_context (
@context_info VARBINARY(128)
)
RETURNS TABLE
AS RETURN (
SELECT
spid = CONVERT(INT, SUBSTRING(@context_info, 1, 4))
,client = CONVERT(VARCHAR(64), SUBSTRING(@context_info, 5, 64))
)
GO
SELECT *
FROM cdc.schema_table_CT s
CROSS APPLY dbo.fn_context(s.ContextInfo) c
দ্রষ্টব্য যে CONTEXT_INFO
কেবলমাত্র 128-বাইট VARBINARY
। আপনার যদি 128 বাইটে ফিট করার চেয়ে আরও বেশি ডেটা দরকার হয় তবে আমি সেই সমস্ত ডেটা ধরে রাখতে একটি টেবিল তৈরি করব, লগন ট্রিগারে সেই সেশনের জন্য সারি হিসাবে সারণিটি সারণি করে সেই টেবিলের CONTEXT_INFO
সারোগেট কী মানটিতে সেট করব
আপনার এটিও লক্ষ্য করা উচিত, যেহেতু এটি কেবল একটি ডিফল্ট সীমাবদ্ধতা, উপযুক্ত-সুবিধাযুক্ত ব্যবহারকারীর পক্ষে বিশ্রাম টেবিলে সেই প্রসঙ্গে ডেটা ওভাররাইট করা তুচ্ছ। অবশ্যই, 'অডিট'-স্টাইলের সারণীতে অন্য সমস্ত কলামগুলির ক্ষেত্রেও এটি একই।
এটি দুর্দান্ত হবে যদি এটি ডিফল্ট না হয়ে স্থির গণিত কলাম হতে পারে তবে CONTEXT_INFO()
ফাংশনটি হ'ল নিয়ন্ত্রক, সুতরাং এটি কোনও FUNCTION
অগ্রগতি নয় (আপনি সম্ভবত একটি ঘেরের কিছু কৌশল ব্যবহার করতে সক্ষম হবেন VIEW
তবে আমি তা করব না) )।
এটি তাদের পক্ষে কল করতে SET CONTEXT_INFO
এবং আপনার দিনকে জগাখিচায় করতে যথেষ্ট অ্যাক্সেস সহ ব্যবহারকারীর পক্ষেও তুচ্ছ (উদাহরণস্বরূপ জাল মান, বা বিশেষত নকশিত সঞ্চিত ইঞ্জেকশন সহ), সুতরাং বিষয়বস্তুকে সন্দেহ এবং যত্নের সাথে আচরণ করুন, প্রদর্শনের আগে এটিকে এনকোড করুন এবং ব্যতিক্রমগুলি পরিচালনা করবেন আমরা হব.
হোস্টনাম হিসাবে, আমি মনে করি ClientHost
উপাদানটি EVENTDATA()
আপনাকে আইপি ঠিকানা দেয় (বা একটি <local machine>
সূচক)। আপনি যখন টেকনিক্যালি হোস্টনেমতে ফিরে বিপরীত-ডিএনএস লকআপগুলি করতে সিএলআর ব্যবহার করতে পারতেন তখন এগুলি প্রত্যেকের জন্য করা খুব ধীর হয়ে যায় INSERT
, তাই আমি এটি না করার পরামর্শ দিই ।
আপনি যদি আছে একটি হোস্ট নাম আছে, আপনি একটি এসকিউএল এজেন্ট কাজ ব্যবহার করতে কিছু সময় অন্তর আপনার স্থানীয় DHCP সার্ভার বা ডিএনএস জোন ফাইল থেকে বর্তমান ইজারা সাথে পৃথক টেবিল নিয়ে আসতে 'একটি আউট-অফ-ব্যান্ড প্রক্রিয়া হিসেবে চান পারে এবং LEFT JOIN
যে হবে ভবিষ্যতের ক্যোয়ারী (বা FUNCTION
পয়েন্ট-ইন-টাইমের জন্য একটি ডিফল্ট সীমাবদ্ধতার মান সরবরাহ করতে একটি স্কেলারে মোড়ানো )
আবার, আপনার মনে রাখা উচিত, যদি অ্যাপ্লিকেশনটিতে কোনও ধরণের পাবলিক-ফেসিং উপাদান থাকে, আইপি ঠিকানা এবং হোস্ট-নেমগুলি অবিশ্বাস্য (যেমন NAT এর কারণে)। এমনকি এটি জনসমক্ষে না থাকলেও বেশিরভাগ আইপি / হোস্টনেম মানচিত্রে একটি নির্দিষ্ট সময় ভিত্তিক উপাদান রয়েছে যা আপনাকে ফ্যাক্টর করার প্রয়োজন হতে পারে।
অবশেষে, আপনার লগইন ট্রিগার প্রয়োগের আগে, এটি আপনার সার্ভারের ডেডিকেটেড অ্যাডমিন সংযোগটি সার্থক হতে পারে। যদি লগইন ট্রিগারটি কোনওভাবে ভেঙে যায় তবে এটি সমস্ত ব্যবহারকারীকে (সিসাদমিন অ্যাকাউন্টগুলি সহ) লগ ইন করা রোধ করতে পারে:
USE master
GO
-- you may want to do this, so you have a back-out if the login trigger breaks login
EXEC sp_configure 'remote admin connections', 1
GO
RECONFIGURE
GO
আপনি যদি লক আউট হয়ে যান, ড্যাক লগইন ট্রিগারটি ড্রপ বা অক্ষম করতে ব্যবহৃত হতে পারে:
C:\> sqlcmd -S localhost -d master -A
1> DISABLE TRIGGER tr_audit_login ON ALL SERVER
2> GO