Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Msg 6522, Peringatan Level 16 selama pelaksanaan prosedur tersimpan clr

Ada beberapa masalah yang terjadi dalam kode ini yang perlu ditangani:

  1. Mengenai pertanyaan yang disebutkan, ketika Anda mendapatkan System.Security.SecurityException kesalahan, yang mengacu pada kode yang mencoba menjangkau di luar basis data, sesuatu yang tidak diizinkan dalam SAFE perakitan. Cara Anda memperbaikinya bergantung pada apa yang ingin Anda capai.

    • Jika Anda mencoba mengakses sistem file, membaca dari registri, mendapatkan variabel lingkungan, mengakses jaringan untuk koneksi non-SQL Server (misalnya http, ftp), dll, maka perakitan memerlukan PERMISSION_SET dari EXTERNAL_ACCESS . Untuk mengatur Majelis Anda ke apa pun selain SAFE , Anda harus:
      • Buat Sertifikat atau Kunci Asimetris berdasarkan kunci yang sama dengan yang Anda gunakan untuk menandatangani Majelis Anda (yaitu beri nama yang kuat), buat Login berdasarkan Sertifikat atau Kunci Asimetris tersebut, lalu berikan EXTERNAL ACCESS ASSEMBLY izin untuk Login itu. Metode ini sangat lebih disukai daripada metode lainnya, yaitu:
      • Setel database yang berisi perakitan ke TRUSTWORTHY ON . Metode ini hanya boleh digunakan sebagai upaya terakhir jika tidak mungkin untuk menandatangani majelis. Atau untuk tujuan pengujian cepat. Menyetel database ke TRUSTWORTHY ON membuka instans Anda terhadap potensi ancaman keamanan dan harus dihindari, meskipun lebih cepat/mudah daripada metode lainnya.
    • Jika Anda mencoba mengakses instance SQL Server yang sudah Anda masuki, maka Anda memiliki opsi untuk menggunakan koneksi dalam proses Context Connection = true; yang dapat dilakukan dalam SAFE perakitan. Inilah yang disarankan @Marc dalam jawabannya. Meskipun pasti ada manfaat menggunakan jenis koneksi ini, dan sementara Koneksi Konteks adalah pilihan yang tepat dalam skenario khusus ini, terlalu sederhana dan salah untuk menyatakan bahwa Anda harus selalu menggunakan jenis koneksi ini. Mari kita lihat aspek positif dan negatif dari Koneksi Konteks :

      • Positif:
        • Dapat dilakukan dengan SAFE perakitan.
        • Sangat rendah, jika ada, overhead koneksi karena ini bukan koneksi tambahan.
        • Adalah bagian dari sesi saat ini sehingga setiap SQL yang Anda jalankan memiliki akses ke item berbasis sesi seperti tabel sementara lokal dan CONTEXT_INFO .
      • Negatif:

        • Tidak dapat digunakan jika Peniruan Identitas telah diaktifkan.
        • Hanya dapat terhubung ke instance SQL Server saat ini.
        • Saat digunakan dalam Fungsi (Skalar dan Bernilai Tabel), ia memiliki semua batasan yang sama dengan fungsi T-SQL (misalnya, tidak ada operasi efek samping yang diizinkan) kecuali Anda dapat menjalankan prosedur tersimpan hanya-baca.
        • Fungsi Bernilai Tabel tidak diizinkan untuk mengalirkan kembali hasilnya jika mereka membaca kumpulan hasil.

        Semua "negatif" ini diizinkan saat menggunakan koneksi reguler/eksternal, meskipun ke instance yang sama dengan tempat Anda mengeksekusi kode ini.

  2. Jika Anda terhubung ke instance tempat Anda mengeksekusi kode ini dan menggunakan koneksi eksternal / reguler, maka tidak perlu menentukan nama Server atau bahkan menggunakan localhost . Sintaks yang disukai adalah Server = (local) yang menggunakan Memori Bersama sedangkan yang lain terkadang menggunakan TCP/IP yang tidak seefisien itu.

  3. Kecuali Anda memiliki alasan yang sangat spesifik untuk melakukannya, jangan gunakan Persist Security Info=True;

  4. Ini adalah praktik yang baik untuk Dispose() dari SqlCommand . Anda

  5. Lebih efisien untuk memanggil insertcommand.Parameters.Add() tepat sebelum for loop, dan kemudian di dalam loop, cukup atur nilainya melalui firstname.Value = , yang sudah Anda lakukan, jadi cukup pindahkan insertcommand.Parameters.Add() baris tepat sebelum for baris.

  6. tel / @tel / listtelnumber adalah INT bukannya VARCHAR / string . Nomor telepon, seperti kode pos dan Nomor Jaminan Sosial (SSN), tidak angka, bahkan jika mereka tampak seperti itu. INT tidak dapat menyimpan 0 leading utama s atau sesuatu seperti ex. untuk menandakan sebuah "ekstensi".

  7. Semua itu dikatakan, bahkan jika semua hal di atas diperbaiki, masih ada masalah besar dengan kode ini yang harus diatasi :ini adalah operasi yang agak sederhana untuk dilakukan dalam T-SQL langsung, dan melakukan ini dalam SQLCLR terlalu rumit, lebih sulit dan lebih mahal untuk dipelihara, dan jauh lebih lambat. Kode ini melakukan 10.000 transaksi terpisah padahal kode ini dapat dengan mudah dilakukan sebagai kueri berbasis kumpulan tunggal (yaitu satu transaksi). Anda bisa membungkus for . Anda loop dalam transaksi yang akan mempercepatnya, tetapi akan selalu lebih lambat daripada pendekatan T-SQL berbasis set karena masih perlu mengeluarkan 10.000 INSERT terpisah pernyataan. Anda dapat dengan mudah mengacak di T-SQL dengan menggunakan NEWID() atau CRYPT_GEN_RANDOM yang diperkenalkan di SQL Server 2008. (silakan lihat UPDATE bagian di bawah)

Jika Anda ingin mempelajari lebih lanjut tentang SQLCLR, silakan lihat seri yang saya tulis untuk SQL Server Central: Tangga ke SQLCLR (perlu pendaftaran gratis).

PERBARUI

Berikut adalah metode T-SQL murni untuk menghasilkan data acak ini, menggunakan nilai dari Pertanyaan. Sangat mudah untuk menambahkan nilai baru ke salah satu dari 4 variabel tabel (untuk menambah jumlah kemungkinan kombinasi) karena kueri secara dinamis menyesuaikan rentang pengacakan agar sesuai dengan data apa pun yang ada di setiap variabel tabel (yaitu baris 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;

Catatan:

  • FULL JOIN s diperlukan alih-alih INNER JOIN s untuk mendapatkan seluruh @RowsToInsert jumlah baris.
  • Baris duplikat dimungkinkan karena sifat pengacakan ini DAN tidak memfilternya dengan menggunakan DISTINCT . Namun, DISTINCT tidak dapat digunakan dengan data sampel yang diberikan dalam pertanyaan karena jumlah elemen dalam setiap variabel array/tabel hanya menyediakan 6300 kombinasi unik dan jumlah baris yang diminta untuk dihasilkan adalah 10.000. Jika lebih banyak nilai ditambahkan ke variabel tabel sehingga total kemungkinan kombinasi unik naik di atas jumlah baris yang diminta, maka DISTINCT kata kunci dapat ditambahkan ke nums CTE, atau kueri dapat direstrukturisasi menjadi CROSS JOIN semua variabel tabel, termasuk ROW_COUNT() bidang, dan ambil TOP(n) menggunakan ORDER BY NEWID() .
  • INSERT dikomentari sehingga lebih mudah untuk melihat bahwa kueri di atas menghasilkan hasil yang diinginkan. Cukup batalkan komentar INSERT agar kueri melakukan operasi DML yang sebenarnya.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kunci Asing SQL Server melintasi batas basis data - teknik untuk penegakan

  2. Galat mengonversi tipe data saat mengimpor dari Excel ke SQL Server 2008

  3. Apakah ada cara untuk melakukan kueri lain dalam kueri penyisipan?

  4. w3wp.exe jaringan tinggi pada panggilan basis data

  5. Bisakah saya mengembalikan varchar(max) dari prosedur tersimpan?