Aggregato definito dall'utente in SQL Server 2008 - Come distribuire con MaxByteSize = -1?
-
05-07-2019 - |
Domanda
Ho letto qui (e altrove) che è possibile, in SQL Server 2008, creare un aggregato definito dall'utente che può restituire una stringa più lunga di 8000 caratteri. Questo è esattamente ciò di cui ho bisogno.
Presumibilmente, il metodo consiste nell'impostare maxByteSize su -1 anziché un numero tra 1 e 8000; questo dovrebbe consentire qualsiasi dimensione fino a 2 GB.
Per qualche motivo, a quanto pare, non è possibile distribuire direttamente da Visual Studio 2008 se si utilizza questa impostazione; quindi è necessario distribuire manualmente.
Quindi: costruisco il mio progetto - GroupConcat (che dovrebbe simulare l'aggregatore group_concat di MySQL) - che mi dà, nella cartella bin del progetto, un file " SqlClassLibrary.dll " ;. Per le istruzioni sulla pagina collegata sopra, ho creato l'assembly in SQL Server. Il comando viene eseguito correttamente. Tuttavia, quando provo a usare l'aggregatore groupconcat:
seleziona reparto, dbo.groupconcat (projectNumber) dal projectlead raggruppa per dipartimento
... dice che non può essere trovato. Funziona tutto bene se imposto maxByteSize su 8000 e lo distribuisco direttamente da VS2008, ma ho bisogno di > 8000. Qualcuno sa cosa sto facendo di sbagliato?
Grazie -Dan
NOTA: in particolare ho bisogno di avere una funzione di aggregazione groupconcat piuttosto che usare alcuni dei trucchi di SQL Server che ho visto spesso.
Soluzione 2
Capito ... Dopo aver creato la soluzione in Vis Studio, supponendo che abbia lasciato cadere il file .dll che crea in c: \ temp e l'ho chiamato GroupConcat.dll:
CREATE ASSEMBLY GroupConcat from 'C:\temp\GroupConcat.dll' with permission_set = safe
GO
CREATE AGGREGATE groupconcat(@input nvarchar(max))
RETURNS nvarchar(max)
EXTERNAL NAME GroupConcat
GO
Lo fa.
Altri suggerimenti
In alternativa, puoi usare la proprietà MaxSize
di SqlFacetAttribute
per indicare la dimensione del varchar. Si noti che nell'esempio seguente ho applicato questo attributo ai parametri SqlString
nel metodo Accumulate
e al valore restituito del metodo Terminate
. Ciò comporta la seguente firma SQL:
AGGREGATE [dbo]. [Concatenate] (@value nvarchar (max), @order int, @seperator nvarchar (max)) RITORNI nvarchar (max)
[Serializable]
[SqlUserDefinedAggregate(
Format.UserDefined,
IsInvariantToOrder = true,
IsInvariantToNulls = true,
IsInvariantToDuplicates = false,
IsNullIfEmpty = false,
MaxByteSize = -1)]
public struct Concatenate : IBinarySerialize
{
public void Init();
public void Accumulate([SqlFacet(MaxSize = -1)] SqlString value,
SqlInt32 order,
[SqlFacet(MaxSize = -1)] SqlString seperator);
public void Merge(Concatenate group);
[return: SqlFacet(MaxSize = -1)]
public SqlString Terminate();
public void Read(BinaryReader r);
public void Write(BinaryWriter w);
}
Non so se questo è più " corretto " rispetto a quello che hai finito per fare, ma sembra più naturale.