,,,
(Sinclair)
(). 3700 , 855 ... , - ; , . , .
RSDN Team MS SQL Server. -, ( ), .
, , . , . .NET MS SQL Server.
, SQL. . SQL (PL/SQL, T-SQL). , , ( Interbase, MS SQL ..).
SQL, . SQL . , , . , PGP T-SQL ( , ). , , .
, . , DLL. , MD5 , .
Oracle Java . , Microsoft .
MS SQL Server .NET:
.
.
( ).
.
.
.NET Framework 1.2 .
, , .NET . (detach/attach) .
:
, T-SQL ( Query Analyzer. , MS SQL Server Workbench, ).
, MS Visual Studio .NET codename Whidbey.
, . .
T-SQL
CREATE ASSEMBLY:
CREATE ASSEMBLY assembly_name [ AUTHORIZATION owner_name ] FROM { < client_assembly_specifier > | < assembly_bits > [,...n] } [ WITH PERMISSION_SET = { SAFE | EXTERNAL_ACCESS | UNSAFE } ] < client_assembly_specifier > :: = '[machine_name]share_name[path]manifest_file_name' < assembly_bits > :: = { varbinary_literal | varbinary_expression } |
. , USE database_name.
assembly_name | .NET (assembly). , MS SQL Server, , . |
AUTHORIZATION owner_name | , . , , , IMPERSONATE. . |
<client_assembly_specifier> | , . . , , . , REFERENCES . , , , , . |
assembly_bits | . , , , . . - MS Visual Studio 8.0 (Whidbey). |
PERMISSION_SET {SAFE | EXTERNAL_ACCESS | UNSAFE } | , MS SQL Server . SAFE.SAFE . ( , , ).EXTERNAL_ACCESS MS SQL Server, . , - .UNSAFE , , . sysadmin. SAFE. , , - SQL Server . SAFE. |
1. CREATE ASSEMBLY.
Visual Studio
- . , . Visual Studio . SQL Server Project ( Database Project!), Build Deploy, ( ) . Visual Studio , .
, Visual Studio T-SQL. , . ( !) . Microsoft.VisualStudio.DataTools.SqlAttributes.
SQL Server, . , , |
System.Data.Sql.SqlAssemblyAttribute. SQL Server Project AssemblyInfo.cs . :
[assembly: SqlAssembly(<name>, Authorization = <authorization>)] |
name assembly_name CREATE ASSEMBLY, Authorization owner_name (. ).
, Visual Studio , , , . .
, . , .
, , , , , , .NET, , . Visual Studio Whidbey, :
, ( Build->Deploy). .
(PID) MS SQL Server. sqlservr.exe. , SQL Server, 3. Yukon MSDE, . , , SELECT ServerProperty('ProcessID')
. Debug->Attach to Process . , Attach.
. , . , .NET.
Debug->Detach All , . Visual Studio , Build.
MS SQL Server CREATE PROCEDURE . SQL Server Books Online:
CREATE PROC [ EDURE ] [schema_name.] procedure_name [ ; number ] [ { @parameter data_type } [ VARYING ] [ = default ] [ [ OUT [ PUT ] ] [ ,...n ] [ WITH < procedure_option > [ ,...n ] [ FOR REPLICATION ] AS { < sql_statement > [ ...n ] | <.NET_Framework_reference> } -- <.NET_Framework_reference> ::= EXTERNAL NAME assembly_name:class_name[::method_name] |
, T-SQL . :
( )
, . OUTPUT, .
, : SQLInt32, SQLInt16, System.Int32, System.Int16
REFERENCES.
.
C# :
using System; using System.Data; using System.Data.Sql; using System.Data.SqlServer; using System.Data.SqlTypes; public class StoredProcedure { [SqlProcedure] public static void MyProcedure() { } }; |
, . , StoredProcedure.MyProcedure , (, Query Analyzer), , ( ).
SqlProcedure (System.Data.Sql.SqlProcedureAttribute). MS SQL Server. MS Visual Studio Whidbey , , CREATE PROCEDURE. , . , Name. [SqlProcedure("MyProcName")], MyProcName.
,
, , C#, . . :
using System; using System.Data; using System.Data.Sql; using System.Data.SqlServer; using System.Data.SqlTypes; public class StoredProcedure { [SqlProcedure("HelloWorld")] public static void MyProcedure() { SqlContext.GetPipe().Send("Hello, Yukon!"); } }; |
, .NET MS SQL Server: System.Data.SqlServer.SqlContext. , , . System.Data.SqlServer.SqlPipe, . SQL Server . - , SqlPipe .
SqlPipe.Send(String msg), . print T-SQL. SqlPipe :
public void Execute (System.Data.SqlServer.SqlCommand command )public void Execute (System.Data.SqlServer.SqlExecutionContext request ) |
. SELECT FROM T-SQL. |
public void Send (System.Data.SqlServer.SqlError se) | . |
public void Send (System.Data.Sql.ISqlReader reader) | . |
public void SendResultsStart (System.Data.Sql.ISqlRecord record , bool sendRow) | . SendingResults true. |
public System.Boolean SendingResults { get; } | , . |
public void SendResultsRow (System.Data.Sql.ISqlRecord record)public void Send (System.Data.Sql.ISqlRecord record ) | . SendingResults == true. |
public void SendResultsEnd ( ) | SendingResults false. |
2.
, , , . .
, :
[SqlProcedure()] public static void CurrencyCourse( [SqlMapping(typeof(SqlDateTime))] DateTime start, [SqlMapping(typeof(SqlDateTime))] DateTime end) { using (SqlCommand cmd = SqlContext.GetCommand()) { cmd.CommandText = @" select changeDate, course from Course where changeDate between @start and @end"; cmd.Parameters.AddWithValue("@start", start); cmd.Parameters.AddWithValue("@end", end); DateTime current = start; SqlDecimal course = SqlDecimal.Null; // ; SqlMetaData[] recstruct = new SqlMetaData[2]; recstruct[0] = new SqlMetaData("D", SqlDbType.DateTime); recstruct[1] = new SqlMetaData("course", SqlDbType.Decimal, 10, 4); SqlDataRecord rec = new SqlDataRecord(recstruct); SqlPipe pipe = SqlContext.GetPipe(); pipe.SendResultsStart(rec, false); using (SqlDataReader r = cmd.ExecuteReader()) { while (r.Read()) { rec.SetSqlDecimal(1, course); while(current < r.GetDateTime(0)) { rec.SetDateTime(0, current); pipe.SendResultsRow(rec); current = current.AddDays(1); } course = r.GetDecimal(1); } } rec.SetSqlDecimal(1, course); while (current <= end) { rec.SetDateTime(0, current); pipe.SendResultsRow(rec); current = current.AddDays(1); } pipe.SendResultsEnd(); } } |
(Course) , , .
. (, MS VS Whidbey) SQL- , SqlMapping (System.Data.Sql.SqlMappingAttribute). . DateTime SQL datetime ( CLR System.Data.SqlTypes.SqlDateTime), .
, SqlContext SqlContext.GetCommand().
, , System.Data.Sql.ISqlRecord. System.Data.Sql.SqlDataRecord. . System.Data.Sql.SqlMetaData. . , SQL :
( D datetime, course decimal(10, 4) ) |
, :
pipe.SendResultsStart(rec, false); |
, ; .
SqlDataReader, , SqlDataRecord, . .
, ,
pipe.SendResultsEnd(); |
, , .. , , . . , .
T-SQL : .
, , . |
.NET, . , . , . :
. .
System.Data.Sql.ISqlReader. . .
void. SqlContext.GetReturnResultSet(). .
.
, ( ). , : select dbo.RevertString(Beavis rulez) |
. reverse:
[SqlFunc()] [SqlFunction( DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, IsDeterministic = true, IsPrecise = true)] public static SqlString RevertString(SqlString str) { if (str.IsNull) return SqlString.Null; System.Text.StringBuilder sb = new System.Text.StringBuilder(str.Value.Length); for (int i=str.Value.Length-1; i>=0; i--) sb.Append(str.Value[i]); return new SqlString(sb.ToString()); } |
, , .
-, SqlFunc. SqlProcedure, , CREATE FUNCTION. , . .
SQLFunction MS SQL Server , . 3 :
DataAccess | :DataAccessKind.None .DataAccessKind.Read . |
SystemDataAccess | :SystemDataAccessKind.None .SystemDataAccessKind.Read . |
IsDeterministic | , .. . |
IsPrecise | . |
3.
, , , .
, , . , , e-mail. , . |
ISqlReader
view , , SQL , . , , :
[SqlFunc(TableDefinition = "D datetime, course decimal(10, 4)")] [SqlFunction(DataAccess = DataAccessKind.Read, SystemDataAccess = SystemDataAccessKind.None, IsDeterministic = false, IsPrecise = true)] public static ISqlReader GetCourseChanges(DateTime start, DateTime end) { SqlCommand cmd = SqlContext.GetCommand(); cmd.CommandText = @" select changeDate, course from Course where changeDate between @start and @end"; cmd.Parameters.AddWithValue("@start", start); cmd.Parameters.AddWithValue("@end", end); return cmd.ExecuteReader(); } |
, . Reader is closed. Reader , . |
SqlResultSet
, , SqlContext.GetReturnResultSet(). , , . . , , / , . CurrencyCourse, :
[SqlFunc(TableDefinition = "D datetime, course decimal(10, 4) NULL")] [SqlFunction(DataAccess = DataAccessKind.Read, SystemDataAccess = SystemDataAccessKind.None, IsDeterministic = false, IsPrecise = true)] public static void GetCourseTable(DateTime start, DateTime end) { using (SqlCommand cmd = SqlContext.GetCommand()) { cmd.CommandText = @" select changeDate, course from Course where changeDate between @start and @end"; cmd.Parameters.AddWithValue("@start", start); cmd.Parameters.AddWithValue("@end", end); DateTime current = start; SqlDecimal course = SqlDecimal.Null; SqlResultSet source = cmd.ExecuteResultSet(ResultSetOptions.None); SqlResultSet dest = SqlContext.GetReturnResultSet(); SqlDataRecord rec; while (source.Read()) { while (current < source.GetDateTime(0)) { rec = dest.CreateRecord(); rec.SetSqlDecimal(1, course); rec.SetDateTime(0, current); dest.Insert(rec); current = current.AddDays(1); } course = source.GetDecimal(1); } while (current <= end) { rec = dest.CreateRecord(); rec.SetDateTime(0, current); rec.SetSqlDecimal(1, course); dest.Insert(rec); current = current.AddDays(1); } } } |
, SqlFunction DataAccess = DataAccessKind.Read, , .
, SqlResultSet SqlDataReader. , , . , . . |
. - MS SQL Server SUM, AVG OUNT.
CREATE AGGREGATE:
CREATE AGGREGATE [ schema_name. ] aggregate_name ( @param_name < input_sqltype > ) RETURNS < return_sqltype > EXTERNAL NAME assembly_name [ :class_name ] < input_sqltype > ::= system_scalar_type | { [ udt_schema_name. ] udt_type_name } < return_sqltype > ::= system_scalar_type | { [ udt_schema_name. ] udt_type_name } |
. . , , . :
public void Init()public void Init(input_type value) | . . , SQL Server . value (input_type) , input_sqltype CREATE AGGREGATE. |
public void Accumulate(input_type value) | , . ( , GROUP BY, distinct . , , ). value , input_sqltype CREATE AGGREGATE. |
public return_type Terminate() | , , . , return_sqltype CREATE AGGREGATE. |
public void Merge(udagg_type group) | , SQL Server . , , . . . , . |
4.
, ( SQL Server ). , , . , .
, , , N N- . ( N , - , N).
, . , N . N ( , 1/N) N Exp(). |
[Serializable] [SqlUserDefinedAggregate(Format.Native, IsInvariantToDuplicates = false, IsInvariantToNulls = true, IsInvariantToOrder = true, IsNullIfEmpty = true)] [StructLayout(LayoutKind.Sequential)] public class AvgGeom: INullable { private double _agg; private int _count; private bool _isNull = true; #region User-Defined Attribute Required Methods public void Init() { _agg = 0; _count = 0; _isNull = true; } public void Accumulate(SqlDouble Value) { if (!Value.IsNull) { _agg += System.Math.Log(Value.Value); _count++; _isNull = false; } } public void Merge(AvgGeom Group) { if (!Group.IsNull) { _agg += Group._agg; _count += Group._count; _isNull = false; } } public SqlDouble Terminate() { if (IsNull) return SqlDouble.Null; else return new SqlDouble(System.Math.Exp(_agg / _count)); } #endregion #region INullable Members public bool IsNull { get { return _isNull; } } #endregion } |
SqlUserDefinedAggregate, . ( 5).
Format | . . |
MaxByteSize | . . |
IsInvariantToDuplicates | ( ). , MIN() , , SUM() . SQL Server Accumulate. |
IsInvariantToNulls | NULL- . ( COUNT()) . |
IsNullIfEmpty | , NULL . , MIN NULL , COUNT() 0. |
IsInvariantToOrder | ; , , Accumulate(). . |
5.
( ) , . , , First() Last(), ( ), . , , , SQL . ORDER BY , , . ( ) ORDER BY . ( !) MS SQL Server Yukon SqlUserDefinedAggregateAttribute.IsInvariantToOrder , - . - . |
, NULL, INullable. read-only bool IsNull. System.Data.SqlTypes . NULL , Null , -NULL Accumulate Merge.
SQL Server (User-defined Types, UDT). CLR- SQL Server. , ( ) -SQL. T-SQL.
T-SQL CREATE TYPE:
CREATE TYPE [ type_schema_name. ] type_name { [ FROM base_type [ ( precision [ , scale ] ) | ( 'urn:schema-namespace' ) ] [ NULL | NOT NULL ] ] | [ EXTERNAL NAME [ assembly_schema_name. ] assembly_name [ :class_name ] ] } |
.
T-SQL, , MS Visual Studio .Net Whidbey. , SqlUserDefinedType ( ) SQL Server Project.
, .NET SQL Server, :
. , , NULL ( ).
NULL-. INullable, . Null, NULL- , .. MyClass.Null.IsNull == true. Null, null.
: Parse(SqlString s) ToString().
. , ( ).
, . .
. , .
using System; using System.Data.Sql; using System.Data.SqlTypes; using System.Text.RegularExpressions; using System.Runtime.InteropServices; [Serializable] [SqlUserDefinedType(Format.Native)] [StructLayout(LayoutKind.Sequential)] public class SqlPoint: INullable { #region NULLability private bool _isNull = true; public bool IsNull { get { return _isNull; } } public static SqlPoint Null { get { return new SqlPoint(); } } #endregion
#region public override string ToString() { return IsNull? "null" : String.Format("X: {0}; Y: {1}", x, y); } public static SqlPoint Parse(SqlString s) { // , // , // ToString SqlPoint. if (s.IsNull || s.Value.ToLower() == "null") return Null; SqlPoint p = new SqlPoint(); Regex t = new Regex(@"x:(?<x>d*(.d+)?)s*W*y:(?<y>d*(.d+)?)", RegexOptions.IgnoreCase); Match match = t.Match(s.Value); p.x = SqlDouble.Parse(match.Groups["x"].Value); p.y = SqlDouble.Parse(match.Groups["y"].Value); return p; } #endregion #region private double _x=0; private double _y=0; public SqlDouble x { get { return IsNull ? SqlDouble.Null : new SqlDouble(_x); } set { if (!value.IsNull) { _x = value.Value; _isNull = false; } } } public SqlDouble y { get { return IsNull? SqlDouble.Null: new SqlDouble(_y); } set { if (!value.IsNull) { _y = value.Value; _isNull = false; } } } public SqlDouble R // . { get { return IsNull ? SqlDouble.Null : new SqlDouble(System.Math.Sqrt(_y*_y +_x*_x)); } set { if (value.IsNull) { _isNull = true; return; } double alpha = Alpha.IsNull? 0 : Alpha.Value; _x = System.Math.Cos(alpha) * value.Value; _y = System.Math.Sin(alpha) * value.Value; } } public SqlDouble Alpha { get { return (IsNull) ? SqlDouble.Null : new SqlDouble(System.Math.Atan2(_y, _x)); } set { if (value.IsNull) { _isNull = true; return; } double r = R.IsNull ? 0 : R.Value; _x = System.Math.Cos(value.Value) * r; _y = System.Math.Sin(value.Value) * r; } } #endregion } |
:
declare @p SqlPoint set @p::x = 3 set @p::y = 4 select @p::x, @p::y, @p::R, @p::ToString() set @p::R = 10 select @p::x, @p::y, @p::R, @p::ToString() set @p::Alpha = 0 select @p::x, @p::y, @p::R, @p::ToString() set @p = convert(SqlPoint, ' x:6; y:5.00') select @p::x, @p::y, @p::R, @p::ToString() |
, 6:
@p::x | @p::y | @p::R | @p::ToString() |
3.0 | 4.0 | 5.0 | X: 3; Y: 4 |
6.0000000000000009 | 7.9999999999999991 | 10.0 | X: 6; Y: 8 |
10.0 | 0.0 | 10.0 | X: 10; Y: 0 |
6.0 | 5.0 | 7.810249675906654 | X: 6; Y: 5 |
6
. .
. get set , . , .
! , SQL Server , . , , . |
T-SQL. , , .
, , .. . select SQL - . . , , , , T-SQL.
:
public SqlDouble ResetR(SqlDouble newR) { SqlDouble Result = R; R = newR; return Result; } |
:
declare @p SqlPoint set @p::x=3 set @p::y=4 select @p::R select @p::ResetR(10) select @p::R |
- ResetR . , .
, SQL Server . SqlMethod IsMutator, true. - . ResetR :
[SqlMethod(IsMutator=true, OnNullCall=false)] public void ResetR2(SqlDouble newR) { R = newR; } |
SqlMethod
SqlMethod (System.Data.Sql.SqlMethodAttribute) SqlFunction, . . , IsMutator, . OnNullCall ; , NULL-. - , .
, . , . SQL Server .
Serializable System.Data.Sql.SqlUserDefinedTypeAttribute.
:
Format
// using System.Data.Sql Format SqlUserDefinedTypeAttribute.Format {get; set} |
. . :
Native - MS SQL Server . , . , , . .NET . , , , , . , System.String ( ) . , [StructLayout(LayoutKind.Sequential)]. SqlUserDefinedTypeAttribute.MaxByteSize.
SerializeDataWithMetaData . , Visual Studio (Project->Add New Item User-Defined Type). , . , Native , .
SerializeData Native SerializeDataWithMetaData. , , . ,
UserDefined , . MaxByteSize , IBinarySerialize. , Native- , .
MaxByteSize
// using System.Data.Sql int SqlUserDefinedTypeAttribute.MaxByteSize {get; set} |
. UserDefined- ( , ). SqlUserDefinedTypeAttribute.MaxByteSizeValue.
IsFixedLength
// using System.Data.Sql bool SqlUserDefinedTypeAttribute.IsFixedLength {get; set} |
, .
IsByteOrdered
// using System.Data.Sql bool SqlUserDefinedTypeAttribute.IsByteOrdered {get; set} |
, , . , . , MS SQL Server , , , order by group by, .
.NET , . , . , - .
T-SQL CREATE TRIGGER:
CREATE TRIGGER trigger_name ON { table | view } [ WITH ENCRYPTION ] { { { FOR | AFTER | INSTEAD OF } { [ INSERT ] [ , ] [ UPDATE ] [ , ] [ DELETE ] } [ WITH APPEND ] [ NOT FOR REPLICATION ] AS { sql_statement [ ...n ] | EXTERNAL NAME < method specifier > } } } < method_specifier > ::= assembly_name:class_name[::method_name] |
, MS Visual Studio Whidbey SQLTrigger:
string Name | , trigger_name T-SQL. |
string ForClause | , . , "INSTEAD OF INSERT, FOR CREATE_ASSEMBLY ( , DDL- ) |
string Target | , . DML- view, DDL- ALL SERVER , DATABASE, . |
7.
. , : SqlTrigger(name, target, forClause) SqlTrigger(target, forClause). |
, :
[SqlTrigger ("DATABASE", "AFTER CREATE_TABLE")] public static void AttachAnotherTrigger() { SqlTriggerContext ctx = SqlContext.GetTriggerContext(); string xml = ctx.EventData.ToSqlString().Value; Regex p = new Regex("<object>(?<tablename>.*)</object>", RegexOptions.IgnoreCase); string tableName = p.Match(xml).Groups["tablename"].Value; SqlContext.GetPipe().Send(String.Format("Table {0} createdn", tableName)); using (SqlCommand cmd = SqlContext.GetCommand()) { cmd.CommandText = String.Format( @"create trigger {0}_insert on {0} for insert as external name TestingYukon:CTriggerTest::AnotherTrigger", tableName); cmd.ExecuteNonQuery(); } } |
DDL- DML . , , SqlChars SqlTriggerContext.EventData. ( ) , , XML. , :
<EVENT_INSTANCE> <PostTime>2004-01-15T04:13:59.600</PostTime> <SPID>56</SPID> <EventType>CREATE_TABLE</EventType> <Database>Northwind</Database> <Schema>dbo</Schema> <Object>testtrigger</Object> <ObjectType>TABLE</ObjectType> <TSQLCommand> <SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON" ANSI_PADDING="ON" QUOTED_IDENTIFIER="ON" ENCRYPTED="FALSE" /> <CommandText>create table testtrigger(id int identity) </CommandText> </TSQLCommand> </EVENT_INSTANCE> |
<object>, ( , XPath XSLT). T-SQL-:
create table testtrigger(id int identity) insert into testtrigger default values drop table testtrigger --drop trigger AttachAnotherTrigger on database |
MS Visual Studio Whidbey DML . , ( ) . . |
EventData, SqlTriggerContext .
TriggerAction ( ) , , <EventType>, EventData.
DML- bool[] ColumnsUpdated , , . T-SQL UPDATE().
inserted deleted ; SqlCommand, GetCommand() SqlContext.
, :
using System; using System.Data; using System.Data.Sql; using System.Data.SqlServer; using System.Data.SqlTypes; using System.Text.RegularExpressions; public class CTriggerTest { [SqlTrigger ("DATABASE", "AFTER CREATE_TABLE")] public static void AttachAnotherTrigger() { SqlTriggerContext ctx = SqlContext.GetTriggerContext(); Regex p = new Regex("<object>(?<tablename>.*)</object>", RegexOptions.IgnoreCase); string xml = ctx.EventData.ToSqlString().Value; string tableName = p.Match(xml).Groups["tablename"].Value; SqlContext.GetPipe().Send(String.Format("Table {0} createdn", tableName)); using (SqlCommand cmd = SqlContext.GetCommand()) { cmd.CommandText = String.Format( @"create trigger {0}_insert on {0} for insert as external name TestingYukon:CTriggerTest::AnotherTrigger", tableName); cmd.ExecuteNonQuery(); } } public static void AnotherTrigger() { SqlContext.GetPipe().Send("Row Insert Interceptedn"); } } |
, AnotherTrigger . , .NET- T-SQL .
MS SQL Server Yukon, .
Yukon Generics
.NET 1.2 Generic-. , .
Yukon .NET, .
, Generic- Yukon . . . , , AvgGeom SqlDouble. . .
, generic- . Yukon . , -, , generic- . - ! GenericType<SQLDecimal> EXTERNAL NAME CREATE .
, generic-. , . :
public new void Init() { base.Init(); } |
. -. , , . , .
. , . |
, , - , . generic :
public interface IAggregating<input_type, return_type> : INullable { void Init(); void Accumulate(input_type value); return_type Terminate(); void Merge(IAggregating<input_type, return_type> other); } |
Yukon . , .
Yukon
.NET- SQL Server , RDBMS. , . , .. CREATE ASSEMBLY.
-, Yukon binary. , TypeA, . . .
-, , - . Yukon . . ( , ).
Yukon
T-SQL . , . .
Yukon
.NET- CREATE ASSEMBLY . , -, , , , , Microsoft. , . CREATE ASSEMBLY, , , .
Yukon
RSDN , SQL-, JAVA, OSP . SQL/PSM, 1996 . , T-SQL . language, , , .NET. Microsoft , .NET.
Microsoft Development Environment Whidbey (8.0.30703.4),
Microsoft .NET Framework 1.2 (1.2.30703),
Microsoft SQL Server Yukon (9.00.608)
Microsoft Word 2003 (11.5604.5703)
Nescafe Gold ( 9198-330-605473-98)
RSDN Authoring Pack (3.1)
MSDN SQL Server Books Online.
http://www.rsdn.ru/
Copyright (c) 2024 Stud-Baza.ru , , , .