2010-03-29 6 views
6

Tôi có một thủ tục lưu trữ đang thực hiện rất nhiều thao tác xóa. Hàng trăm ngàn hồ sơ. Nó sẽ không được chạy từ ứng dụng, nhưng tôi vẫn lo ngại rằng một trong những khách hàng của tôi vô tình chạy nó (tôi đã có vấn đề trước đó do "sự tò mò" của họ): DCó một "bạn có chắc chắn" để thực hiện thủ tục lưu trữ không? :)

Có. có những bản sao lưu và những thứ như thế, nhưng tôi đã suy nghĩ .... không sợ họ ... có cách nào để hỏi người dùng "bạn có chắc không?" trước khi thực hiện nó? :) cảm ơn

+10

Tại sao bạn không thiết lập quyền cho procs được lưu trữ của mình? Bằng cách đó, chỉ những người dùng được ủy quyền mới có thể chạy nó. –

+0

@ The Gentleman Elite: Tôi không nói rằng người dùng có thẩm quyền đôi khi có thể muốn cảm thấy như con người chứ không phải là máy móc. Trường hợp cụ thể này cho thấy rằng một số nhà phát triển không nhớ người dùng chỉ là những người chết. :) –

Trả lời

7

Tôi đoán bạn có thể có tham số được gọi là "xác nhận" yêu cầu một chuỗi cụ thể (e, g, "Tôi biết mình đang làm gì") được chuyển vào, nếu chưa được đặt, hoặc được đặt không chính xác, chỉ cần trả lại từ quy trình mà không cần thực thi mã chính. Không chính xác những gì bạn muốn, nhưng nó là một lựa chọn.

ví dụ - (cú pháp chưa được kiểm tra và có lẽ khủng khiếp)

CREATE PROCEDURE dbo.mySproc (
@Confirmation Varchar(100) 
) AS 
BEGIN 
    if(@Confirmation <> 'I know what I am doing') 
    BEGIN 
     return; 
    END 
    DELETE from table_name where condition 
END 
+0

Nó có thể hoạt động, nhưng tôi nghĩ rằng nó sẽ nhanh chóng trở thành một "Sao chép & Dán & Bỏ qua Tham số" –

+4

Đồng ý, nhưng không có gì để ngăn chặn chúng bỏ qua bất cứ điều gì nếu họ có quyền truy cập vào sproc trực tiếp anyway. Tốt hơn hết nên thêm quyền truy cập/thực thi bảo mật thích hợp xung quanh toàn bộ sự việc. – ZombieSheep

+0

+1 Tôi đồng ý hoàn toàn, đây là vấn đề kỷ luật –

6

Nói tóm lại, không có.

Lý thuyết cho rằng bất kỳ ai có quyền tìm và có thể chạy thủ tục được lưu trữ đều phải được cho phép. Nó sẽ là tốt hơn để hạn chế quyền để những người có một sự tò mò dư thừa không có quyền để chạy này.

Các khác, kém an toàn, lựa chọn sẽ được yêu cầu là một bí mật được xác định trước mà cần phải được thông qua như một tham số - dĩ nhiên họ có thể chỉ kịch bản các thủ tục lưu trữ off để tìm ra bí mật mặc dù ...

Tất nhiên, điểm khác sẽ là: Nếu nó không được gọi, tại sao lại bao gồm nó? Sau khi tất cả, khi bạn đến để thực hiện các tác vụ kiểu quản trị, bạn có thể có các câu lệnh được viết thành tệp mà bạn có thể giữ an toàn trên máy của riêng mình

1

Bạn có thể sử dụng đầu vào bit được gọi là @UserKnowsWhatTheyAreDoing và kiểm tra xem nó có đúng trước khi thực thi. Nếu sai, in một thông báo thân thiện và trả về một cách duyên dáng từ quy trình

2

Bạn có thể thêm tham số @reallyReallyReallyDelete vào sproc.

1

Quy trình có thể yêu cầu đối số với một giá trị cụ thể, như 'Yes I know what I'm doing'. Hoặc nó có thể tìm kiếm một hàng một bảng đặc biệt với một xác nhận tương tự và một dấu thời gian gần đây.

3

sử dụng một cách tiếp cận mũi nhọn nhiều tầng:

1) kiểm soát thực thi an ninh, như:

GRANT EXECUTE ON [dbo].[yourProcedure] TO [userxyz] 

2) sử dụng một/tên thủ tục đáng sợ thực sự mô tả, như

CREATE PROCEDURE Will_Delete_All_Your_Data ... 

3) đặt một chú thích bắt mắt lớn khi bắt đầu quy trình được lưu trữ

--NOTE, will delete all of your data-- 
--NOTE, will delete all of your data-- 
--NOTE, will delete all of your data-- 
--NOTE, will delete all of your data-- 
--NOTE, will delete all of your data-- 

4) làm cho đèo người sử dụng trong một mã truy cập đặc biệt obfuscated:

CREATE PROCEDURE Will_Delete_All_Your_Data 
(
    @SpecialCode varchar(30) 
) 

IF @SpecialCode!=CHAR(83)+CHAR(112)+CHAR(101)+CHAR(99)+CHAR(105)+CHAR(97)+CHAR(108)+CHAR(67)+CHAR(111)+CHAR(100)+CHAR(101) 
BEGIN 
    RETURN 999 
END 
... 

FYI, các mã đặc biệt phải là 'SpecialCode' hoặc TRẢ LẠI 999 là hit.

0

Bạn có cần thực sự xóa chúng khỏi DB không? Nếu tôi có thể đủ khả năng cho không gian thêm tôi sẽ đặt một lá cờ 'Đã xóa' trong các bảng của tôi và cột được cập nhật lần cuối. Bằng cách này nếu một hồ sơ vô tình bị xóa ít nhất tôi thường có thể theo dõi nó xuống và khôi phục lại nó khá dễ dàng. Chỉ là một ý nghĩ.

1

Dưới đây là một cách tiếp cận khác, mà tôi nghĩ là phù hợp cho trường hợp cụ thể khi một thủ tục được gọi trực tiếp bởi người dùng thay vì từ một ứng dụng.

Tôi phải nói, nó đề xuất ít rắc rối hơn cho người dùng trong khi nhiều hơn (có thể, không cân xứng) cho nhà phát triển so với hầu hết các đề xuất khác. Bạn quyết định liệu nó có phù hợp với bạn hay không.

Dù sao, ở đây đi.

Trước tiên, bạn tạo một bảng đặc biệt, CriticalCalls, để đăng ký cuộc gọi đến các thủ tục quan trọng. Bảng sẽ có một cấu trúc như thế này:

SPID int, 
ProcName sysname, 
CallTime datetime 

Về cơ bản, ý tưởng là một SP quan trọng nên được gọi là hai lần: lần đầu tiên nó đăng ký cuộc gọi và thông báo cho người sử dụng để lặp lại các cuộc gọi trong một khoảng thời gian nhất định như xác nhận ý định của họ và với cuộc gọi thứ hai, nếu được thực hiện tương ứng, nó thực sự tiến hành hoàn thành nhiệm vụ của mình.

Vì vậy, các phần khởi động của tất cả các thủ tục quan trọng sẽ có logic này:

IF NOT EXISTS (
    SELECT * 
    FROM CriticalCalls 
    WHERE SPID = @@SPID AND ProcName = @ThisProcName 
    AND GETDATE() - CallTime BETWEEN @LowerCallTimeLimit AND @UpperCallTimeLimit 
    /* the actual test for the time interval might be somewhat different */ 
) BEGIN 
    ... /* upsert CriticalCalls with the current time stamp */ 
    PRINT 'To proceed, please call this procedure again within...'; 
    RETURN; 
END; 

DELETE FROM CriticalCalls WHERE SPID = @@SPID AND ProcName = @ThisProcName; 

... /* proceed with your critical task */ 

Thực ra, tôi nghĩ rằng, nó sẽ là tốt nhất để sử dụng một SP chuyên dụng (tên CheckCriticalCalls dưới đây) cho tất cả các thao tác với CriticalCalls, bao gồm tất cả các sửa đổi cần thiết. CheckCriticalCalls sẽ nhận được tên của thủ tục được kiểm tra và trả về một loại cờ cho biết liệu quy trình được chỉ định có nên thực hiện hoạt động thực của nó hay không.

Vì vậy, nó có thể trông khá như thế này:

EXECUTE @result = CheckCriticalCalls 'ThisProcedureName'; 
IF @result = -1 BEGIN 
    PRINT 'Call me again'; 
    RETURN; 
END; 

... /* go on with the task */ 

Ý tưởng đằng sau thiết lập các giới hạn dưới của khoảng chỉ đơn thuần là để ngăn chặn người dùng từ gọi một thủ tục quan trọng gấp đôi tự động, tức là bằng cách thực hiện hai giống hệt EXECUTE... dòng trong một đợt. Giới hạn trên, tất nhiên, là cần thiết để 1) đảm bảo rằng người dùng xác nhận ý định gần đây của họ để thực hiện các hoạt động quan trọng; 2) ngăn chặn thực hiện nếu bản ghi hiện tại trong CriticalCalls thực sự được để lại ở đó từ một phiên trước đó có cùng SPID.

Vì vậy, về cơ bản, khoảng thời gian từ 1-2 giây đến nửa phút có vẻ khá tự nhiên đối với tôi. Thay vào đó, bạn có thể chọn các hình khác nhau.