[〜#〜]問題[〜#〜]
SMScounter.Counter
は、サービスからの使用量を累積するために使用されます。このサービスのプログラムによる上限は1000です。この上限に違反した場合はユーザーに警告します。
テーブル作成
CREATE TABLE [dbo].[SMSCounter](
[Counter] [int] NOT NULL,
[CounterDate] [datetime] NOT NULL )
例のデータ
380, 2012-09-10 00:00:00.000
177, 2012-10-14 00:00:00.000
999, 2012-11-16 00:00:00.000
ジョブスクリプト
以下のスクリプトは、SMScounter.Counter
は950より大きい。
USE DATABASEname
select (Counter) as CHECKVALUE from SMSCounter where smscounter.CounterDate = DATEADD(dd, DATEDIFF(dd, 0, GETDATE()),0)
IF CHECKVALUE > 950
BEGIN
EXEC msdb.dbo.sp_send_dbmail
@recipients=N'[email protected]',
@body='1000 Daily SMS cap near',
@subject ='1000 Daily SMS cap near',
@profile_name ='SCOTT',
@query =
'USE DATABASEname
(select * from SMSCounter where CounterDate = GETDATE())'
END
[〜#〜]質問[〜#〜]
GETDATE
をフォーマットして調べるにはどうすればよいですかdd/mm/yy
を読み、時間部分を無視するSMScounter.CounterDate
? (上記のスクリプトは編集済みで、現在は機能しています)。
IF
を950と比較するためにCHECKVALUE
ステートメントを機能させるにはどうすればよいですか?
SQL Server 2008 Standard Editionを使用しています。
convert (date, GETDATE())
を使用して、「日付」部分のみを取得できます。
select GETDATE(), convert (date, GETDATE())
----------------------- ----------
2012-11-16 08:58:20.750 2012-11-16
また、「日付」の部分のみを比較する場合は、クエリを実行するたびに変換する手間を省くために、テーブルのデータ型をDATE
に変更することをお勧めします。
IF
ステートメントの場合、チェックする値を渡し、実行するコードをBEGIN
およびEND
ステートメント内にラップする必要があります。次に、sysobjectsテーブルを使用した例を示します。
declare @cnt integer
select @cnt=COUNT(1) from sysobjects
if @cnt>50
begin
select 'hello'
end
dBに50を超えるオブジェクトがある場合、こんにちはと言います
だからあなたの場合:
USE DATABASEname
go
declare @counter integer
select @counter=MAX([Counter]) from SMSCounter where convert(date,CounterDate) = convert(date,GETDATE())
IF @counter > 950
BEGIN
EXEC msdb.dbo.sp_send_dbmail
@recipients=N'[email protected]',
@body='1000 Daily SMS cap near',
@subject ='1000 Daily SMS cap near',
@profile_name ='SCOTT',
@query = '(select * from DATABASEname.dbo.SMSCounter where convert(date,CounterDate) = convert)(Date,GETDATE()))'
END
チェッククエリにMAX
関数を追加しました。これにより、その日の最大値を含む単一の行のみが返されます。それ以外の場合は、一致するすべての行からランダムな値が返されます。テーブルに書き込むたびにその日の値を上書きする場合、それは不必要です。
解決策は悪くありませんが、もっとリアルタイムなものを紹介したいと思います。 SMSカウンターを1時間ごとにチェックするだけではなく、それがいつ最初に発生したかを知っているでしょうか?
私は次のようにします:
新しい列をテーブルに追加します-警告ビットはデフォルトではnullではありません-顧客が大量のSMSについて警告を受けた場合に情報を保持します。これは、950を超えるすべての挿入/更新について顧客に警告が表示されるのではなく、最初の挿入/更新についてのみ警告が表示されるようにするために必要です。
カウンターの値が950より大きい場合にアラートを開始する(挿入および更新後)テーブルにトリガーを追加します(アラート列を1に設定して電子メールを送信します)。
トリガーは次のようになります。
ALTER TRIGGER dbo.RaiseAlert
ON dbo.SMSCounter
AFTER INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
declare
@cnt int,
@today DATE = cast(GETDATE() as DATE),
@alert bit;
select @cnt = n.[Counter], @alert = alert
from inserted n
where n.CounterDate = @today;
if @cnt > 950 and @alert = 0
begin
update SMSCounter
set Alert = 1
from SMSCounter
where CounterDate = @today;
declare @subject varchar(1000);
select @subject = 'The sms counter is near!! It''s value is: ' + CAST(@cnt as varchar);
EXEC msdb.dbo.sp_send_dbmail @profile_name='SQLAlerts',
@recipients = '[email protected]',
@subject = @subject,
@body = 'blablabla';
end;
END
GO
単純な更新でそれが発生し、電子メールが送信されます。
update SMSCounter
set [Counter] = 988
where CounterDate = '2012-11-16 00:00:00.000'
これを@query
パラメータで機能させることができなかったため、代わりにHTMLを使用しました
スクリプトは、「sa
」またはサービスアカウントを使用してログインしているユーザーを監査します
IF OBJECT_ID ('AuditSqlLogins') IS NOT NULL DROP TABLE AuditSqlLogins
GO
CREATE TABLE AuditSqlLogins (
[Counter] [int] IDENTITY(1,1) NOT NULL,
[Login_name] [varchar](20) NULL,
[Host_name] [varchar](20) NULL,
[login_time] [datetime] NULL
) ON [PRIMARY]
INSERT INTO [dbo].[AuditSqlLogins]
(login_time, login_name, Host_name )
SELECT login_time, login_name, Host_name
FROM sys.dm_exec_sessions
WHERE Host_name not like '%APP%' -- excludeds Apllication server logins
and Host_name not like '%WWW%' -- excludeds Web server logins
and database_id = 5 -- Specify the database you want to audit
and login_name = 'Appadmin' -- specify the account you want audited
or login_name = 'sa'
ORDER BY Host_name desc
DELETE FROM AuditSqlLogins
WHERE Host_name is null
DECLARE @counter integer
SELECT @counter = Counter FROM AuditSqlLogins
IF (@counter > 0)
BEGIN
DECLARE @xml NVARCHAR(MAX)
SET @xml = CAST ( ( SELECT
td = login_name , '',
td = Host_name, '',
td = login_time,''
FROM AuditSqlLogins
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) )
DECLARE @body nvarchar(max);
SET @body ='
<html>
<body>
<head>
<style>
table {
border-collapse: collapse;
}
table, th, td {
border: 1px solid #ea5685;
}
</style>
</head>
<H3>Audit Appadmin and SA Login Event : (Server Name)</H3>
<table border="1" cellspacing="0" border-spacing="0" style ="text-align:center">
<tr style="height:15px; background:#ea8686">
<th border-spacing="0" style="padding:5px 15px;">login_name</th>
<th border-spacing="0" style="padding:5px 15px;">Host_name</th>
<th border-spacing="0" style="padding:5px 15px;">login_time</th>
</tr>
'
SET @body = @body+@xml+'</table><body>'
EXEC msdb.dbo.sp_send_dbmail
@recipients='[email protected]',
@subject = 'Audit itsadmin and SA Login Event',
@body = @body,
@body_format = 'HTML' ,
@profile_name='Your DB Mail profile'
END
DROP TABLE AuditSqlLogins