sql >> Databasteknik >  >> RDS >> Sqlserver

Msg 6522, nivå 16 varning under exekvering av clr lagrad procedur

Det finns flera problem som pågår i den här koden som måste åtgärdas:

  1. Angående den angivna frågan, när du får en System.Security.SecurityException fel, som hänvisar till koden som försöker nå utanför databasen, något som inte är tillåtet i en SAFE hopsättning. Hur du åtgärdar detta beror på vad du försöker åstadkomma.

    • Om du försöker komma åt filsystemet, läsa från registret, hämta en miljövariabel, få åtkomst till nätverket för en icke-SQL-serveranslutning (t.ex. http, ftp), etc, så behöver sammansättningen en PERMISSION_SET av EXTERNAL_ACCESS . För att ställa in din assembly på något annat än SAFE måste du antingen:
      • Skapa ett certifikat eller asymmetrisk nyckel baserat på samma nyckel som du använde för att signera din sammansättning (dvs. ge den ett starkt namn), skapa en inloggning baserat på det certifikatet eller asymmetriska nyckeln och ge sedan EXTERN ÅTKOMST MONTERING behörighet att logga in. Den här metoden är mycket föredras framför den andra metoden, som är:
      • Ställ in databasen som innehåller sammansättningen till TRUSTWORTHY ON . Denna metod bör endast användas som en sista utväg om det inte är möjligt att signera sammansättningen. Eller för snabba teständamål. Ställer in en databas på TRUSTWORTHY ON öppnar din instans för potentiella säkerhetshot och bör undvikas, även om det är snabbare/enklare än den andra metoden.
    • Om du försöker komma åt SQL Server-instansen som du redan är inloggad på, har du möjlighet att använda den pågående anslutningen av Context Connection =true; vilket kan göras i en SAFE hopsättning. Detta är vad @Marc föreslog i sitt svar. Även om det definitivt finns fördelar med att använda den här typen av anslutning, och även om kontextanslutningen var det lämpliga valet i det här specifika scenariot, är det alltför förenklat och felaktigt att säga att du alltid ska använd denna typ av anslutning. Låt oss titta på de positiva och negativa aspekterna av Kontextkopplingen :

      • Positivt:
        • Kan göras i en SAFE montering.
        • Mycket låg, om någon, anslutningskostnad eftersom det inte är en extra anslutning.
        • Är en del av den aktuella sessionen så att alla SQL du kör har tillgång till sessionsbaserade objekt som lokala temporära tabeller och CONTEXT_INFO .
      • Negativa:

        • Kan inte användas om identitetsstöld har aktiverats.
        • Kan bara ansluta till den aktuella SQL Server-instansen.
        • När den används i funktioner (skalär och tabellvärderad) har den samma begränsningar som T-SQL-funktioner har (t.ex. inga sidoverkande operationer är tillåtna) förutom att du kan köra skrivskyddade lagrade procedurer.
        • Tabellvärderade funktioner får inte streama sina resultat tillbaka om de läser en resultatuppsättning.

        Alla dessa "negativa" är tillåtna när du använder en vanlig/extern anslutning, även om det är till samma instans som du kör den här koden från.

  2. Om du ansluter till instansen som du kör den här koden från och använder en extern/vanlig anslutning behöver du inte ange servernamnet eller ens använda localhost . Den föredragna syntaxen är Server =(lokal) som använder delat minne medan de andra ibland kan använda TCP/IP som inte är lika effektivt.

  3. Använd inte Persist Security Info=True; om du inte har en mycket specifik anledning till att göra det.

  4. Det är en god praxis att Kassera() av ditt SqlCommand

  5. Det är mer effektivt att anropa insertcommand.Parameters.Add() precis före för loop, och sedan inuti loopen, ställ helt enkelt in värdet via firstname.Value = , vilket du redan gör, så flytta bara insertcommand.Parameters.Add() rader till strax före för rad.

  6. tel / @tel / listtelnummer är INT istället för VARCHAR / sträng . Telefonnummer, precis som postnummer och personnummer (SSN), är inte siffror, även om de verkar vara det. INT kan inte lagra inledande 0 s eller något som ex. för att beteckna en "förlängning".

  7. Allt detta sagt, även om allt ovan är korrigerat, finns det fortfarande ett stort problem med den här koden som bör åtgärdas :detta är en ganska förenklad operation att utföra i rak T-SQL, och att göra detta i SQLCLR är alltför komplicerat, svårare och dyrare att underhålla och mycket långsammare. Den här koden utför 10 000 separata transaktioner medan den så lätt kan göras som en enda uppsättningsbaserad fråga (dvs en transaktion). Du kan slå in din för slinga i en transaktion som skulle påskynda den, men den kommer fortfarande alltid att vara långsammare än den uppsättningsbaserade T-SQL-metoden eftersom den fortfarande behöver utfärda 10 000 separata INSERT uttalanden. Du kan enkelt randomisera i T-SQL genom att använda antingen NEWID() eller CRYPT_GEN_RANDOM som introducerades i SQL Server 2008. (se UPPDATERING avsnitt nedan)

Om du vill lära dig mer om SQLCLR, kolla in serien jag skriver för SQL Server Central: Trappa till SQLCLR (gratis registrering krävs).

UPPDATERA

Här är en ren T-SQL-metod för att generera denna slumpmässiga data, med hjälp av värdena från frågan. Det är lätt att lägga till nya värden till någon av de fyra tabellvariablerna (för att öka antalet möjliga kombinationer) eftersom frågan dynamiskt justerar randomiseringsintervallet för att passa vilken data som finns i varje tabellvariabel (d.v.s. rad 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;

Anmärkningar:

  • FULL JOIN s behövs istället för INNER JOIN s för att få hela @RowsToInsert antal rader.
  • Duplicerade rader är möjliga på grund av själva karaktären av denna randomisering OCH att inte filtrera bort dem med DISTINCT . Men DISTINCT kan inte användas med givna exempeldata i frågan eftersom antalet element i varje array/tabellvariabel endast ger 6300 unika kombinationer och det begärda antalet rader att generera är 10 000. Om fler värden läggs till i tabellvariablerna så att det totala antalet möjliga unika kombinationer stiger över det begärda antalet rader, kan antingen DISTINCT nyckelord kan läggas till i nums CTE, eller frågan kan omstruktureras till att helt enkelt CROSS JOIN all tabellvariabel, inkluderar en ROW_COUNT() och ta tag i TOP(n) med ORDER BY NEWID() .
  • INSERT kommenteras bort så att det är lättare att se att frågan ovan ger önskat resultat. Kommentera bara INSERT för att få frågan att utföra den faktiska DML-operationen.


  1. Booleska fält i MySQL Django-modeller?

  2. Kan jag använda ett Postgres-nyckelord som ett alias i den valda listan?

  3. DPI-1047:64-bitars Oracle Client-bibliotek kan inte laddas

  4. Reverse Engineering för databasdiagram i Visio med SQL Server 2008