Có một số vấn đề đang xảy ra trong mã này cần được giải quyết:
-
Về câu hỏi đã nêu, khi bạn nhận được System.Security.SecurityException lỗi, đề cập đến mã đang cố gắng truy cập bên ngoài cơ sở dữ liệu, điều không được phép trong
SAFE
hội,, tổ hợp. Cách bạn khắc phục điều này phụ thuộc vào những gì bạn đang cố gắng hoàn thành.- Nếu bạn đang cố gắng truy cập hệ thống tệp, đọc từ sổ đăng ký, lấy biến môi trường, truy cập mạng cho kết nối không phải SQL Server (ví dụ:http, ftp), v.v., thì hợp ngữ cần có
PERMISSION_SET
trong tổng sốEXTERNAL_ACCESS
. Để đặt assembly của bạn thành bất kỳ thứ gì khác ngoàiSAFE
, bạn cần:- Tạo Chứng chỉ hoặc Khóa không đối xứng dựa trên cùng một khóa mà bạn đã sử dụng để ký hợp đồng của mình (tức là đặt tên mạnh cho nó), tạo Đăng nhập dựa trên Chứng chỉ hoặc Khóa không đối xứng đó, rồi cấp
EXTERNAL ACCESS ASSEMBLY
quyền đăng nhập đó. Phương pháp này rất nhiều được ưa thích hơn phương pháp khác, đó là: - Đặt cơ sở dữ liệu chứa hội đồng thành
TRUSTWORTHY ON
. Phương pháp này chỉ nên được sử dụng như một phương sách cuối cùng nếu không thể ký hợp đồng. Hoặc cho các mục đích kiểm tra nhanh chóng. Đặt cơ sở dữ liệu thànhTRUSTWORTHY ON
mở ra phiên bản của bạn trước các mối đe dọa bảo mật tiềm ẩn và nên tránh, ngay cả khi nhanh hơn / dễ dàng hơn so với phương pháp khác.
- Tạo Chứng chỉ hoặc Khóa không đối xứng dựa trên cùng một khóa mà bạn đã sử dụng để ký hợp đồng của mình (tức là đặt tên mạnh cho nó), tạo Đăng nhập dựa trên Chứng chỉ hoặc Khóa không đối xứng đó, rồi cấp
-
Nếu bạn đang cố gắng truy cập phiên bản SQL Server mà bạn đã đăng nhập, thì bạn có tùy chọn sử dụng kết nối trong quá trình của
Context Connection = true;
có thể được thực hiện trongSAFE
hội,, tổ hợp. Đây là những gì @Marc đề xuất trong câu trả lời của anh ấy. Mặc dù chắc chắn có những lợi ích khi sử dụng loại kết nối này và mặc dù Kết nối theo ngữ cảnh là lựa chọn thích hợp trong trường hợp cụ thể này, nhưng việc tuyên bố rằng bạn nên luôn luôn là quá đơn giản và không chính xác. sử dụng loại kết nối này. Hãy xem xét các khía cạnh tích cực và tiêu cực của Kết nối theo ngữ cảnh :- Tích cực:
- Có thể được thực hiện trong
SAFE
lắp ráp. - Chi phí kết nối rất thấp, nếu có, vì nó không phải là kết nối bổ sung.
- Là một phần của phiên hiện tại nên bất kỳ SQL nào bạn thực thi đều có quyền truy cập vào các mục dựa trên phiên như các bảng tạm thời cục bộ và
CONTEXT_INFO
.
- Có thể được thực hiện trong
-
Phủ định:
- Không thể sử dụng nếu tính năng Mạo danh đã được bật.
- Chỉ có thể kết nối với phiên bản SQL Server hiện tại.
- Khi được sử dụng trong các Hàm (Scalar và Table-Valued), nó có tất cả các hạn chế giống như các hàm T-SQL (ví dụ:không cho phép các hoạt động tác động bên) ngoại trừ bạn có thể thực thi các thủ tục được lưu trữ chỉ đọc.
- Các hàm được định giá trong bảng không được phép truyền phát lại kết quả của chúng nếu chúng đọc một tập kết quả.
Tất cả các "phủ định" này đều được phép khi sử dụng kết nối thông thường / kết nối bên ngoài, ngay cả khi kết nối đó với cùng trường hợp mà bạn đang thực thi mã này.
- Tích cực:
- Nếu bạn đang cố gắng truy cập hệ thống tệp, đọc từ sổ đăng ký, lấy biến môi trường, truy cập mạng cho kết nối không phải SQL Server (ví dụ:http, ftp), v.v., thì hợp ngữ cần có
-
Nếu bạn đang kết nối với phiên bản mà bạn đang thực thi mã này từ đó và sử dụng kết nối bên ngoài / thông thường, thì không cần chỉ định Tên máy chủ hoặc thậm chí sử dụng
localhost
. Cú pháp ưu tiên làServer = (local)
cái này sử dụng Bộ nhớ dùng chung trong khi những cái khác đôi khi có thể sử dụng TCP / IP không hiệu quả. -
Trừ khi bạn có một lý do rất cụ thể để làm như vậy, không sử dụng
Persist Security Info=True;
-
Một phương pháp hay là
Dispose()
trong sốSqlCommand
của bạn -
Sẽ hiệu quả hơn nếu gọi
insertcommand.Parameters.Add()
ngay trướcfor
và sau đó bên trong vòng lặp, chỉ cần đặt giá trị quafirstname.Value =
, mà bạn đang làm, vì vậy chỉ cần di chuyểninsertcommand.Parameters.Add()
các dòng ngay trướcfor
dòng. -
tel
/@tel
/listtelnumber
làINT
thay vìVARCHAR
/string
. Số điện thoại, giống như mã zip và Số an sinh xã hội (SSN), không số, ngay cả khi chúng có vẻ như vậy.INT
không thể lưu trữ0
đầu s hoặc cái gì đó nhưex.
để biểu thị một "tiện ích mở rộng". -
Tất cả những điều đó đang được nói, ngay cả khi tất cả những điều trên đã được sửa chữa, vẫn còn một vấn đề lớn với mã này cần được giải quyết :đây là một hoạt động khá đơn giản để thực hiện trong T-SQL thẳng và thực hiện điều này trong SQLCLR là quá phức tạp, khó hơn và tốn kém hơn để bảo trì và chậm hơn nhiều. Mã này đang thực hiện 10.000 giao dịch riêng biệt trong khi nó có thể dễ dàng được thực hiện như một truy vấn dựa trên tập hợp duy nhất (tức là một giao dịch). Bạn có thể bọc
for
lặp lại trong một giao dịch sẽ tăng tốc độ, nhưng nó vẫn sẽ luôn chậm hơn so với cách tiếp cận T-SQL dựa trên bộ vì nó vẫn cần phát hành 10.000INSERT
riêng biệt các câu lệnh. Bạn có thể dễ dàng sắp xếp ngẫu nhiên trong T-SQL bằng cách sử dụngNEWID()
hoặc CRYPT_GEN_RANDOM được giới thiệu trong SQL Server 2008. (vui lòng xem CẬP NHẬT phần bên dưới)
Nếu bạn muốn tìm hiểu thêm về SQLCLR, hãy xem loạt bài tôi đang viết cho SQL Server Central: Nấc thang lên SQLCLR (yêu cầu đăng ký miễn phí).
CẬP NHẬT
Đây là một phương pháp T-SQL thuần túy để tạo dữ liệu ngẫu nhiên này, sử dụng các giá trị từ Câu hỏi. Có thể dễ dàng thêm các giá trị mới vào bất kỳ biến nào trong số 4 biến bảng (để tăng số lượng kết hợp có thể có) vì truy vấn điều chỉnh động phạm vi ngẫu nhiên để phù hợp với bất kỳ dữ liệu nào có trong mỗi biến bảng (tức là hàng 1 - n).
DECLARE @TelNumber TABLE (TelNumberID INT NOT NULL IDENTITY(1, 1),
Num VARCHAR(30) NOT NULL);
INSERT INTO @TelNumber (Num) VALUES ('1525407'), ('5423986'), ('1245398'), ('32657891'),
('123658974'), ('7896534'), ('12354698');
DECLARE @FirstName TABLE (FirstNameID INT NOT NULL IDENTITY(1, 1),
Name NVARCHAR(30) NOT NULL);
INSERT INTO @FirstName (Name) VALUES ('Babak'), ('Carolin'), ('Martin'), ('Marie'),
('Susane'), ('Michail'), ('Ramona'), ('Ulf'), ('Dirk'), ('Sebastian');
DECLARE @LastName TABLE (LastNameID INT NOT NULL IDENTITY(1, 1),
Name NVARCHAR(30) NOT NULL);
INSERT INTO @LastName (Name) VALUES ('Bastan'), ('Krause'), ('Rosner'),
('Gartenmeister'), ('Rentsch'), ('Benn'), ('Kycik'), ('Leuoth'),
('Kamkar'), ('Kolaee');
DECLARE @Address TABLE (AddressID INT NOT NULL IDENTITY(1, 1),
Addr NVARCHAR(100) NOT NULL);
INSERT INTO @Address (Addr) VALUES ('Deutschlan Chemnitz Sonnenstraße 59'), (''),
('Deutschland Chemnitz Arthur-Strobel straße 124'),
('Deutschland Chemnitz Brückenstraße 3'),
('Iran Shiraz Chamran Blvd, Niayesh straße Nr.155'), (''),
('Deutschland Berlin Charlotenburg Pudbulesky Alleee 52'),
('United State of America Washington DC. Farbod Alle'), ('');
DECLARE @RowsToInsert INT = 10000;
;WITH rowcounts AS
(
SELECT (SELECT COUNT(*) FROM @TelNumber) AS [TelNumberRows],
(SELECT COUNT(*) FROM @FirstName) AS [FirstNameRows],
(SELECT COUNT(*) FROM @LastName) AS [LastNameRows],
(SELECT COUNT(*) FROM @Address) AS [AddressRows]
), nums AS
(
SELECT TOP (@RowsToInsert)
(CRYPT_GEN_RANDOM(1) % rc.TelNumberRows) + 1 AS [RandomTelNumberID],
(CRYPT_GEN_RANDOM(1) % rc.FirstNameRows) + 1 AS [RandomFirstNameID],
(CRYPT_GEN_RANDOM(1) % rc.LastNameRows) + 1 AS [RandomLastNameID],
(CRYPT_GEN_RANDOM(1) % rc.AddressRows) + 1 AS [RandomAddressID]
FROM rowcounts rc
CROSS JOIN msdb.sys.all_columns sac1
CROSS JOIN msdb.sys.all_columns sac2
)
-- INSERT dbo.Unsprstb(Firstname, Lastname, Tel, Address)
SELECT fn.Name, ln.Name, tn.Num, ad.Addr
FROM @FirstName fn
FULL JOIN nums
ON nums.RandomFirstNameID = fn.FirstNameID
FULL JOIN @LastName ln
ON ln.LastNameID = nums.RandomLastNameID
FULL JOIN @TelNumber tn
ON tn.TelNumberID = nums.RandomTelNumberID
FULL JOIN @Address ad
ON ad.AddressID = nums.RandomAddressID;
Ghi chú:
-
FULL JOIN
s là cần thiết thay vìINNER JOIN
s để nhận toàn bộ@RowsToInsert
số lượng hàng. - Có thể có các hàng trùng lặp do bản chất của việc ngẫu nhiên hóa này VÀ không lọc chúng ra bằng cách sử dụng
DISTINCT
. Tuy nhiên,DISTINCT
không thể được sử dụng với dữ liệu mẫu đã cho trong câu hỏi vì số phần tử trong mỗi biến mảng / bảng chỉ cung cấp cho 6300 kết hợp duy nhất và số hàng được yêu cầu để tạo là 10.000. Nếu nhiều giá trị hơn được thêm vào các biến bảng sao cho tổng số kết hợp duy nhất có thể có tăng trên số hàng được yêu cầu thìDISTINCT
từ khóa có thể được thêm vàonums
CTE hoặc truy vấn có thể được cấu trúc lại thànhCROSS JOIN
tất cả biến bảng, bao gồmROW_COUNT()
và lấyTOP(n)
sử dụngORDER BY NEWID()
. -
INSERT
được nhận xét ra nên dễ dàng thấy rằng truy vấn trên tạo ra kết quả mong muốn. Chỉ cần bỏ ghi chúINSERT
để truy vấn thực hiện thao tác DML thực tế.