Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Msg 6522, cảnh báo mức 16 trong khi thực hiện thủ tục lưu trữ clr

Có một số vấn đề đang xảy ra trong mã này cần được giải quyết:

  1. 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ài SAFE , 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ành TRUSTWORTHY 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.
    • 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 trong SAFE 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 .
      • 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.

  2. 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ả.

  3. 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;

  4. Một phương pháp hay là Dispose() trong số SqlCommand của bạn

  5. Sẽ hiệu quả hơn nếu gọi insertcommand.Parameters.Add() ngay trước for và sau đó bên trong vòng lặp, chỉ cần đặt giá trị qua firstname.Value = , mà bạn đang làm, vì vậy chỉ cần di chuyển insertcommand.Parameters.Add() các dòng ngay trước for dòng.

  6. tel / @tel / listtelnumberINT 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".

  7. 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.000 INSERT 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ụng NEWID() 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ào nums CTE hoặc truy vấn có thể được cấu trúc lại thành CROSS JOIN tất cả biến bảng, bao gồm ROW_COUNT() và lấy TOP(n) sử dụng ORDER 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ế.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Vòng lặp trên bảng (Không sử dụng con trỏ) để nối dữ liệu

  2. Định dạng ngày được trả về là mm / dd / yyyy hh:mm:ss AM / PM

  3. Giá trị thập lục phân 0x00 là một ký tự không hợp lệ

  4. NOCHECK không vô hiệu hóa các tham chiếu khóa ngoại

  5. SaveChanges () không lưu dữ liệu