Há vários problemas acontecendo neste código que precisam ser resolvidos:
-
Em relação à pergunta declarada, quando você recebe uma System.Security.SecurityException erro, que se refere ao código tentando alcançar fora do banco de dados, algo que não é permitido em umSAFE
conjunto. Como você corrige isso depende do que você está tentando realizar.
- Se você estiver tentando acessar o sistema de arquivos, ler do registro, obter uma variável de ambiente, acessar a rede para uma conexão não-SQL Server (por exemplo, http, ftp), etc, o assembly precisa de um
PERMISSION_SET
deEXTERNAL_ACCESS
. Para definir seu assembly para algo diferente deSAFE
, você precisa:- Crie um certificado ou chave assimétrica com base na mesma chave que você usou para assinar seu assembly (ou seja, dê um nome forte), crie um login com base nesse certificado ou chave assimétrica e conceda o
EXTERNAL ACCESS ASSEMBLY
permissão para esse Login. Este método é muito preferido sobre o outro método, que é: - Defina o banco de dados que contém o assembly para
TRUSTWORTHY ON
. Este método só deve ser usado como último recurso se não for possível assinar o assembly. Ou para fins de teste rápido. Configurando um banco de dados paraTRUSTWORTHY ON
abre sua instância para possíveis ameaças de segurança e deve ser evitada, mesmo que seja mais rápido/fácil do que o outro método.
- Crie um certificado ou chave assimétrica com base na mesma chave que você usou para assinar seu assembly (ou seja, dê um nome forte), crie um login com base nesse certificado ou chave assimétrica e conceda o
-
Se você estiver tentando acessar a instância do SQL Server na qual já está conectado, terá a opção de usar a conexão em processo deContext Connection = true;
que pode ser feito em umSAFE
conjunto. Isso é o que @Marc sugeriu em sua resposta. Embora haja definitivamente benefícios em usar esse tipo de conexão, e embora a Conexão de Contexto tenha sido a escolha apropriada nesse cenário específico, é muito simplista e incorreto afirmar que você deve sempre usar este tipo de conexão. Vejamos os aspectos positivos e negativos da Conexão de contexto :
- Positivos:
- Pode ser feito em um
SAFE
montagem. - Muito baixa, se houver, sobrecarga de conexão, pois não é uma conexão adicional.
- Faz parte da sessão atual para que qualquer SQL que você execute tenha acesso a itens baseados em sessão, como tabelas temporárias locais e
CONTEXT_INFO
.
- Pode ser feito em um
-
Negativos:
- Não pode ser usado se a representação estiver ativada.
- Só pode se conectar à instância atual do SQL Server.
- Quando usado em funções (escalar e com valor de tabela), ele tem todas as mesmas restrições que as funções T-SQL têm (por exemplo, nenhuma operação de efeito colateral é permitida), exceto que você pode executar procedimentos armazenados somente leitura. >
- As funções com valor de tabela não têm permissão para transmitir seus resultados de volta se lerem um conjunto de resultados.
Todos esses "negativos" são permitidos ao usar uma conexão regular/externa, mesmo que seja para a mesma instância da qual você está executando este código.
- Positivos:
- Se você estiver tentando acessar o sistema de arquivos, ler do registro, obter uma variável de ambiente, acessar a rede para uma conexão não-SQL Server (por exemplo, http, ftp), etc, o assembly precisa de um
-
Se você estiver se conectando à instância da qual está executando este código e usando uma conexão externa/regular, não será necessário especificar o nome do servidor ou mesmo usarlocalhost
. A sintaxe preferida éServer = (local)
que usa Memória Compartilhada enquanto os outros às vezes podem usar TCP/IP que não é tão eficiente.
-
A menos que você tenha um motivo muito específico para fazer isso, não usePersist Security Info=True;
-
É uma boa práticaDispose()
do seuSqlCommand
-
É mais eficiente chamar oinsertcommand.Parameters.Add()
logo antes dofor
loop e, em seguida, dentro do loop, basta definir o valor por meio defirstname.Value =
, o que você já está fazendo, então apenas mova oinsertcommand.Parameters.Add()
linhas imediatamente antes dofor
linha.
-
tel
/@tel
/listtelnumber
sãoINT
em vez deVARCHAR
/string
. Números de telefone, assim como CEPs e Números de Seguro Social (SSNs), não números, mesmo que pareçam ser.INT
não é possível armazenar o0
inicial s ou algo comoex.
para significar uma "extensão".
-
Tudo isso dito, mesmo que todos os itens acima sejam corrigidos, ainda há um grande problema com este código que deve ser resolvido :esta é uma operação bastante simplista para executar em T-SQL direto, e fazer isso em SQLCLR é muito complicado, mais difícil e mais caro de manter e muito mais lento. Este código está realizando 10.000 transações separadas, enquanto poderia ser feito tão facilmente como uma única consulta baseada em conjunto (ou seja, uma transação). Você pode envolver seufor
loop em uma transação que a aceleraria, mas ainda será sempre mais lenta do que a abordagem T-SQL baseada em conjunto, pois ainda precisa emitir 10.000INSERT
separados declarações. Você pode facilmente randomizar em T-SQL usandoNEWID()
ou CRYPT_GEN_RANDOM que foi introduzido no SQL Server 2008. (consulte o UPDATE seção abaixo)
Se você quiser saber mais sobre SQLCLR, confira a série que estou escrevendo para o SQL Server Central: Escadaria para SQLCLR (inscrição gratuita obrigatória).
ATUALIZAÇÃO
Aqui está um método T-SQL puro de gerar esses dados aleatórios, usando os valores da pergunta. É fácil adicionar novos valores a qualquer uma das 4 variáveis da tabela (para aumentar o número de combinações possíveis), pois a consulta ajusta dinamicamente o intervalo de randomização para ajustar os dados em cada variável da tabela (ou seja, linhas 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;
Notas:
- O
FULL JOIN
s são necessários em vez deINNER JOIN
s para obter todo o@RowsToInsert
quantidade de linhas. - Linhas duplicadas são possíveis devido à própria natureza dessa randomização E não filtrá-las usando
DISTINCT
. No entanto,DISTINCT
não pode ser usado com os dados de amostra fornecidos na pergunta, pois o número de elementos em cada variável de matriz/tabela fornece apenas 6.300 combinações únicas e o número solicitado de linhas a serem geradas é 10.000. Se mais valores forem adicionados às variáveis da tabela de forma que o total de combinações únicas possíveis fique acima do número de linhas solicitado, então oDISTINCT
palavra-chave pode ser adicionada aonums
CTE, ou a consulta pode ser reestruturada para simplesmenteCROSS JOIN
todas as variáveis da tabela, inclua umROW_COUNT()
campo e pegue oTOP(n)
usandoORDER BY NEWID()
. - O
INSERT
é comentada para que seja mais fácil ver que a consulta acima produz o resultado desejado. Apenas descomente oINSERT
para que a consulta faça a operação DML real.