Bir SQL CLR ilgili sorun ile kişisel bir arkadaşa (aynı zamanda bir istemci de) yardımcı olmaya çalışıyorum. İçinde 3 .NET derleme yerleşik bir veritabanı ile SQL Server vardır. veritabanından derlemeleri çıkarmasına yardım etmemi ve diskte .dll dosyaları olarak kaydetmememi istedi. Bu mümkün mü?Bir SQL derlemesi SQL Server 2005'ten ayıklanıyor
cevap
Evet, bu mümkün. Derlemelerin gerçek ikili gösterimi, sunucunuz için SQL kataloğunda yaşar. Yani, sys.assembly_files ve sys.assemblies arasında bir birleşimi çalıştırırsanız, gereksiniminiz olan tüm bilgilere ulaşabilirsiniz. Derlemeler ikili, sys.assembly_files görünümünün içerik sütununda bulunur.
Fakat SQL Server ve montajlar şimdi bulunduğu ifade aynı veritabanı üzerinde çalıştırmak için gereken bazı .NET kodu yazmak zorunda kalacak diskte dosyasına ikili gösterimini elde etmek için
. Görsel Studio'da SQL CLR proje başlatmak ve aşağıdaki kodla kendisine bir sınıf ekleyin:using System;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Security.Permissions;
namespace ExtractSqlAssembly {
[PermissionSet(SecurityAction.Demand, Unrestricted = true, Name = "FullTrust")]
public partial class SaveSqlAssembly {
[SqlProcedure]
public static void SaveAssembly(string assemblyName, string path) {
string sql = @"SELECT AF.content FROM sys.assembly_files AF JOIN sys.assemblies A ON AF.assembly_id = A.assembly_id where AF.file_id = 1 AND A.name = @assemblyname";
using (SqlConnection conn = new SqlConnection("context connection=true")) {
using (SqlCommand cmd = new SqlCommand(sql, conn)) {
SqlParameter param = new SqlParameter("@assemblyname", SqlDbType.VarChar);
param.Value = assemblyName;
cmd.Parameters.Add(param);
cmd.Connection.Open(); // Read in the assembly byte stream
SqlDataReader reader = cmd.ExecuteReader();
reader.Read();
SqlBytes bytes = reader.GetSqlBytes(0);
// write the byte stream out to disk
FileStream bytestream = new FileStream(path, FileMode.CreateNew);
bytestream.Write(bytes.Value, 0, (int)bytes.Length);
bytestream.Close();
}
}
}
}
}
Ardından projeyi oluşturmak ve veritabanına dağıtın. SQL Server'da CLR Etkin yapılandırma seçeneğinin etkinleştirildiğinden emin olun. Bu, muhtemelen meclisleriniz olduğundan, zaten etkin.
sp_configure 'clr enabled', 1
go
reconfigure
go
bilmeniz gereken bir şey daha var varsayılan SQL sunucusu tarafından ise yazmayı izin vermeyebilir: durumunda clr yürütme değil Bunu etkinleştirmek için SSMS üzerinde aşağıdaki kodu çalıştırabilir etkin olduğunu .NET kodundan diske. Yukarıdaki kodu, SSMS'de saklı yordamı çağırarak çalıştırdığınızda bir FileIO güvenlik hatası alırsanız, derlemesi için uygun izin kümesini yapılandırmanız gerekir. Bunu SSMS ile yapabilirsiniz: Yeni düzeneği sağ tıklayın ve Özellikler iletişim kutusundaki İzin Kümesi'ne 'a bakın. Harici Erişim olarak ayarlayın. Şimdi SSMS aşağıdaki kodu çalıştırarak meclisleri dışa gerekir: Bu sizin için çalışan
exec SaveAssembly 'AssemblyName', 'f:\path\to\assemblyname.dll'
Umut ...
Evet.
Eğer
DECLARE @IMG_PATH VARBINARY(MAX)
DECLARE @ObjectToken INT
SELECT @IMG_PATH = content FROM sys.assembly_files WHERE assembly_id = 65536
EXEC sp_OACreate 'ADODB.Stream', @ObjectToken OUTPUT
EXEC sp_OASetProperty @ObjectToken, 'Type', 1
EXEC sp_OAMethod @ObjectToken, 'Open'
EXEC sp_OAMethod @ObjectToken, 'Write', NULL, @IMG_PATH
EXEC sp_OAMethod @ObjectToken, 'SaveToFile', NULL, 'c:\temp\myassembly.dll', 2
EXEC sp_OAMethod @ObjectToken, 'Close'
EXEC sp_OADestroy @ObjectToken
müthiş altında görün. Basit ve temiz. Teşekkür ederim. –
preet çözümü benim için çalıştı istediğiniz toplanma id bulmak için bir select * from sys.assembly_files
, ama ben SQL Server 2008 R2 üzerinde çalışmak için Ole Otomasyon yapılandırmak zorunda kaldı. Ayrıca, SQL Server'ın bu dizine izinleri olmadıkça, SaveToFile çalışmaz - bir hata iletisi de verir. Benim durumumda, iyi çalışan SQL Server örneğinin veri klasörünü kullandım.
EXECUTE SP_CONFIGURE 'show advanced options', 1
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE WITH OVERRIDE
GO
DECLARE @IMG_PATH VARBINARY(MAX)
DECLARE @ObjectToken INT
SELECT @IMG_PATH = content FROM sys.assembly_files WHERE assembly_id = 65546
EXEC sp_OACreate 'ADODB.Stream', @ObjectToken OUTPUT
EXEC sp_OASetProperty @ObjectToken, 'Type', 1
EXEC sp_OAMethod @ObjectToken, 'Open'
EXEC sp_OAMethod @ObjectToken, 'Write', NULL, @IMG_PATH
EXEC sp_OAMethod @ObjectToken, 'SaveToFile', NULL, 'C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\myassembly.dll', 2
EXEC sp_OAMethod @ObjectToken, 'Close'
EXEC sp_OADestroy @ObjectToken
EXEC sp_configure 'Ole Automation Procedures', 0;
RECONFIGURE WITH OVERRIDE
GO
EXECUTE SP_CONFIGURE 'show advanced options', 0
RECONFIGURE WITH OVERRIDE
GO
Jonas'ın yaklaşım aynı zamanda bir konsol uygulaması veya LINQPad komut dosyası gibi çalışıyor - o da anlaşılacağı gibi kod SQL süreci içinde yerel olarak yürütülecek gerek yoktur.örneğin bir veritabanından tSQLt takımını (bir test aracı) ayıklanması:
void Main()
{
var assemblyName = "tSQLtCLR";
var serverName = "localhost";
var databaseName = "MyDb";
var targetDir = Environment.ExpandEnvironmentVariables("%TEMP%");
var targetFile = Path.Combine(targetDir, assemblyName) + ".dll";
var sql = @"SELECT AF.content FROM sys.assembly_files AF JOIN sys.assemblies A ON AF.assembly_id = A.assembly_id where AF.file_id = 1 AND A.name = @assemblyName";
var connectionString = string.Format("Data Source={0};Initial Catalog={1};Integrated Security=true", serverName, databaseName);
using(var connection = new System.Data.SqlClient.SqlConnection(connectionString)){
connection.Open();
var command = connection.CreateCommand();
command.CommandText = sql;
command.Parameters.Add("@assemblyName", assemblyName);
using(var reader = command.ExecuteReader()){
if(reader.Read()){
var bytes = reader.GetSqlBytes(0);
File.WriteAllBytes(targetFile, bytes.Value);
Console.WriteLine(targetFile);
}else{
throw new Exception("No rows returned");
}
}
}
}
Preet ve Nate çözümlerini alarak ve bir gösterici kullanarak TÜM clr procs ihraç edecek bir komut dosyası dönüştürerek:
EXECUTE SP_CONFIGURE 'show advanced options', 1
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE WITH OVERRIDE
GO
RAISERROR ('Starting...', 0, 1) WITH NOWAIT
DECLARE @ObjectToken INT
DECLARE @AssemblyLocation VARCHAR(MAX)
DECLARE @Msg VARCHAR(MAX)
DECLARE @Content VARBINARY(MAX)
DECLARE @Count AS INT = (SELECT COUNT(name) FROM sys.assembly_files)
DECLARE AssemblyFiles CURSOR FAST_FORWARD
FOR
SELECT
CAST(ROW_NUMBER() OVER (ORDER BY name) AS VARCHAR(10)) + ' of ' + CAST(@Count AS VARCHAR(10)) + ' - ' + name AS Msg,
'[a location the server can write to]' + name + '.dll' AS AssemblyLocation,
content
FROM
sys.assembly_files
ORDER BY
name
OPEN AssemblyFiles
FETCH NEXT FROM AssemblyFiles
INTO @Msg, @AssemblyLocation, @Content
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC sp_OACreate 'ADODB.Stream', @ObjectToken OUTPUT
EXEC sp_OASetProperty @ObjectToken, 'Type', 1
EXEC sp_OAMethod @ObjectToken, 'Open'
EXEC sp_OAMethod @ObjectToken, 'Write', NULL, @Content
EXEC sp_OAMethod @ObjectToken, 'SaveToFile', NULL, @AssemblyLocation, 2
EXEC sp_OAMethod @ObjectToken, 'Close'
EXEC sp_OADestroy @ObjectToken
RAISERROR (@Msg, 0, 1) WITH NOWAIT
FETCH NEXT FROM AssemblyFiles
INTO @Msg, @AssemblyLocation, @Content
END
CLOSE AssemblyFiles
DEALLOCATE AssemblyFiles
RAISERROR ('Done', 0, 1) WITH NOWAIT
EXEC sp_configure 'Ole Automation Procedures', 0;
RECONFIGURE WITH OVERRIDE
GO
EXECUTE SP_CONFIGURE 'show advanced options', 0
RECONFIGURE WITH OVERRIDE
GO
ben Bu soruna daha basit bir çözüm bulmuştur, çünkü gerekli olan sp_OACreate
'un SQL Server 2017 için mevcut olmadığı (en azından Linux sürümü).
/opt/mssql-tools/bin/bcp "SELECT content FROM sys.assembly_files WHERE name = '${ASSEMBLY_NAME}'" \
queryout /tmp/my_assembly.so -f bcp.fmt \
-S localhost -U sa -P "${SA_PASSWORD}" -d master
Ve bu biçim dosyası (BCP.FMT) kullanın:
Sadece çok gibi diskteki bir dosyaya takımını yazmak için BCP yardımcı programını kullanabilirsiniz
13.0
1
1 SQLBINARY 0 0 "" 1 content ""
sonuçtaki dosya (/tmp/my_assembly.so), aşağıdaki gibi bir derlemenin oluşturulmasında kullanılabilir:
CREATE ASSEMBLY [MyAssembly] AUTHORIZATION [dbo]
FROM '/tmp/my_assembly.so' WITH PERMISSION_SET = SAFE;
- 1. Sql Server CLR yükleme derlemesi başarısız oldu
- 2. Sadece SQL Server'da bir DLL SQL derlemesi bulma
- 3. SQL Server
- 4. SQL Server
- 5. SQL Server
- 6. SQL Server
- 7. SQL Server
- 8. SQL Server
- 9. SQL Server
- 10. Sql Server
- 11. SQL Server
- 12. SQL Server
- 13. SQL Server, bir 'durum'
- 14. [SQL Server]
- 15. SQL Server:
- 16. SQL Server Profiler SQL deyiminde
- 17. SQL Server şemasını bir SQL sorgusuyla alın?
- 18. SQL Server Fulltext arama ben bir SQL Server tablosuna sahip
- 19. SQL Server'da SQL Server eşdeğeri SQL Server değişkenleri nedir? Dinamik SQL yazarken Oracle
- 20. SQL Server: tek bir soru
- 21. SQL Server 2012'de SQL Enjeksiyonu
- 22. SQL Server: Ben mantıksal olarak bazı verileri dönmelidir SQL Server üzerinde bir SQL sorgusu çalıştırıyorum verileri
- 23. SQL Server Karma Dizinleri
- 24. SQL Server 2008
- 25. SQL Server 2008 R2
- 26. SQL Server 2008
- 27. SQL Server 2005:
- 28. SQL Server Dönüş Yok
- 29. Zor: SQL Server tarafında
- 30. İçindeki SQL Server 2000
Bu yaklaşım, ext yürütüldüğünde düzgün çalışır son derece - SQLCLR yoluna gitmeniz gerekmez. Benim cevabımın – piers7