كيف أفعل SELECT * INTO [temp table] FROM [stored procedure]
؟ لا FROM [Table]
ودون تحديد [temp table]
؟
Select
جميع البيانات من BusinessLine
إلى tmpBusLine
تعمل بشكل جيد.
select *
into tmpBusLine
from BusinessLine
أحاول نفس الشيء ، لكن استخدام stored procedure
الذي يعرض البيانات ، ليس هو نفسه تمامًا.
select *
into tmpBusLine
from
exec getBusinessLineHistory '16 Mar 2009'
رسالة الإخراج:
Msg 156 ، المستوى 15 ، الحالة 1 ، السطر 2 بناء جملة غير صحيح بالقرب من الكلمة الأساسية "exec".
لقد قرأت العديد من الأمثلة لإنشاء جدول مؤقت بنفس بنية الإجراء المخزن للإخراج ، والذي يعمل بشكل جيد ، ولكن سيكون من الجيد عدم توفير أي أعمدة.
يمكنك استخدام OPENROWSET لهذا الغرض. الق نظرة. لقد قمت أيضًا بتضمين شفرة sp_configure لتمكين استعلامات Ad Hoc الموزعة ، في حالة عدم تمكينها بالفعل.
CREATE PROC getBusinessLineHistory
AS
BEGIN
SELECT * FROM sys.databases
END
GO
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO
SELECT * INTO #MyTempTable FROM OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
'EXEC getBusinessLineHistory')
SELECT * FROM #MyTempTable
إذا كنت تريد القيام بذلك دون الإعلان أولاً عن الجدول المؤقت ، فيمكنك محاولة إنشاء دالة معرفة من قبل المستخدم بدلاً من إجراء مخزن وجعل هذه الدالة المعرفة من قبل المستخدم تقوم بإرجاع جدول. بدلاً من ذلك ، إذا كنت تريد استخدام الإجراء المخزن ، فحاول إجراء شيء مثل هذا:
CREATE TABLE #tmpBus
(
COL1 INT,
COL2 INT
)
INSERT INTO #tmpBus
Exec SpGetRecords 'Params'
في SQL Server 2005 ، يمكنك استخدام INSERT INTO ... EXEC
لإدراج نتيجة الإجراء المخزن في جدول. من وثائق INSERT
MSDN (لـ SQL Server 2000 ، في الواقع):
--INSERT...EXECUTE procedure example
INSERT author_sales EXECUTE get_author_sales
هذه إجابة على نسخة معدلة قليلاً من سؤالك. إذا كان يمكنك التخلي عن استخدام إجراء مخزن لوظيفة معرفة من قبل المستخدم ، فيمكنك استخدام دالة معرفة من قبل المستخدم مضمنة في الجدول. هذا بشكل أساسي إجراء مخزن (سيستغرق معلمات) يقوم بإرجاع جدول كمجموعة نتائج ؛ وبالتالي سوف تضع بشكل جيد مع بيان INTO.
إليك مقالة جيدة سريعة عليها ووظائف أخرى معرفة من قبل المستخدم. إذا كنت لا تزال بحاجة إلى القيادة لإجراء مخزّن ، فيمكنك الالتفاف على الوظيفة المعرفة من قبل المستخدم والمضمنة في الجدول ، مع إجراء مخزن. يقوم الإجراء المخزن بتمرير المعلمات فقط عند استدعاء تحديد * من الدالة المعرفة من قبل المستخدم المضمنة في الجدول.
على سبيل المثال ، سيكون لديك دالة معرّفة من قِبل المستخدم في الجدول مضمنة للحصول على قائمة العملاء لمنطقة معينة:
CREATE FUNCTION CustomersByRegion
(
@RegionID int
)
RETURNS TABLE
AS
RETURN
SELECT *
FROM customers
WHERE RegionID = @RegionID
GO
يمكنك بعد ذلك استدعاء هذه الوظيفة للحصول على نتائجك على النحو التالي:
SELECT * FROM CustomersbyRegion(1)
أو للقيام باختيار:
SELECT * INTO CustList FROM CustomersbyRegion(1)
إذا كنت لا تزال بحاجة إلى إجراء مخزن ، فقم بلف الوظيفة على هذا النحو:
CREATE PROCEDURE uspCustomersByRegion
(
@regionID int
)
AS
BEGIN
SELECT * FROM CustomersbyRegion(@regionID);
END
GO
أعتقد أن هذه هي الطريقة "الأقل اختراقًا" للحصول على النتائج المرجوة. يستخدم الميزات الموجودة لأنها كانت مخصصة للاستخدام دون تعقيدات إضافية. عن طريق تداخل دالة معرّفة من قِبل المستخدم في الجدول المخزن في الإجراء المخزن ، يمكنك الوصول إلى الوظيفة بطريقتين. زائد! لديك نقطة صيانة واحدة فقط لرمز SQL الفعلي.
تم اقتراح استخدام OPENROWSET ، لكن هذا ليس ما كانت وظيفة OPENROWSET مخصصة لاستخدامه (من Books Online):
يتضمن جميع معلومات الاتصال المطلوبة للوصول إلى البيانات عن بعد من مصدر بيانات DB OLE. هذه الطريقة هي بديل للوصول إلى الجداول في خادم مرتبط وهي طريقة مخصصة لمرة واحدة للاتصال والوصول إلى البيانات عن بعد باستخدام OLE DB. للحصول على إشارات أكثر تواتراً إلى OLE مصادر بيانات DB ، استخدم الخوادم المرتبطة بدلاً من ذلك.
سيؤدي استخدام OPENROWSET إلى إنجاز المهمة ، لكنه سيتكبد بعض النفقات الإضافية الإضافية لفتح الاتصالات المحلية وتنظيم البيانات. قد لا يكون أيضًا خيارًا في جميع الحالات نظرًا لأنه يتطلب إذنًا لاستعلام مخصص يمثل خطرًا على الأمان وبالتالي قد لا يكون مرغوبًا فيه. أيضا ، فإن نهج OPENROWSET يحول دون استخدام الإجراءات المخزنة بإرجاع أكثر من مجموعة نتائج واحدة. يمكن أن يؤدي التفاف الوظائف المتعددة المعرفة من قبل المستخدم إلى جدول مضمّن في إجراء مخزن واحد إلى تحقيق ذلك.
EXEC sp_serveroption 'YOURSERVERNAME', 'DATA ACCESS', TRUE
SELECT *
INTO #tmpTable
FROM OPENQUERY(YOURSERVERNAME, 'EXEC db.schema.sproc 1')
الحل الأسهل:
CREATE TABLE #temp (...); INSERT INTO #temp EXEC [sproc];
إذا كنت لا تعرف المخطط ، فيمكنك القيام بما يلي. يرجى ملاحظة أن هناك مخاطر أمنية شديدة في هذه الطريقة.
SELECT *
INTO #temp
FROM OPENROWSET('SQLNCLI',
'Server=localhost;Trusted_Connection=yes;',
'EXEC [db].[schema].[sproc]')
عندما يقوم الإجراء المخزن بإرجاع الكثير من الأعمدة ولا ترغب في "إنشاء" جدول مؤقت يدويًا للاحتفاظ بالنتيجة ، فقد وجدت أن أسهل طريقة هي الانتقال إلى الإجراء المخزن وإضافة جملة "إلى" حدد آخر عبارة وأضف 1 = 0 إلى جملة أين.
تشغيل الإجراء المخزن مرة واحدة والعودة وإزالة رمز SQL الذي أضفته للتو. الآن ، سيكون لديك جدول فارغ يطابق نتيجة الإجراء المخزن. يمكنك إما "جدول نصي كإنشاء" لجدول مؤقت أو ببساطة إدراج مباشرة في هذا الجدول.
declare @temp table
(
name varchar(255),
field varchar(255),
filename varchar(255),
filegroup varchar(255),
size varchar(255),
maxsize varchar(255),
growth varchar(255),
usage varchar(255)
);
INSERT @temp Exec sp_helpfile;
select * from @temp;
إذا كان جدول نتائج proc المخزن الخاص بك معقدًا جدًا بحيث لا يمكن كتابة عبارة "إنشاء جدول" يدويًا ، ولا يمكنك استخدام OPENQUERY OR OPENROWSET ، فيمكنك استخدام sp_help لإنشاء قائمة الأعمدة و أنواع البيانات بالنسبة لك. بمجرد حصولك على قائمة الأعمدة ، إنها مجرد تنسيق لتناسب احتياجاتك.
الخطوة 1: إضافة "إلى #temp" إلى استعلام الإخراج (على سبيل المثال "حدد [...] في #temp من [...]").
أسهل طريقة هي تحرير استعلام الإخراج في proc مباشرةً. إذا لم تتمكن من تغيير proc المخزنة ، فيمكنك نسخ المحتويات في نافذة استعلام جديدة وتعديل الاستعلام هناك.
الخطوة 2: تشغيل sp_help على الجدول المؤقت. (على سبيل المثال "exec tempdb..sp_help #temp")
بعد إنشاء جدول temp ، قم بتشغيل sp_help على جدول temp للحصول على قائمة بالأعمدة وأنواع البيانات بما في ذلك حجم حقول varchar.
الخطوة 3: نسخ أعمدة وأنواع البيانات في بيان إنشاء جدول
لدي ورقة Excel يمكنني استخدامها لتنسيق إخراج sp_help في عبارة "إنشاء جدول". لا تحتاج إلى أي شيء يتوهم ، فقط قم بنسخه ولصقه في محرر SQL الخاص بك. استخدم أسماء الأعمدة والأحجام والأنواع لإنشاء عبارة "إنشاء جدول #x [...]" أو "إعلانx جدول [...]" والتي يمكنك استخدامها لإدراج نتائج الإجراء المخزن.
الخطوة 4: إدراج في الجدول المنشأ حديثا
سيكون لديك الآن استعلام يشبه الحلول الأخرى الموضحة في هذا الموضوع.
DECLARE @t TABLE
(
--these columns were copied from sp_help
COL1 INT,
COL2 INT
)
INSERT INTO @t
Exec spMyProc
يمكن أيضًا استخدام هذه التقنية لتحويل جدول مؤقت (#temp
) إلى متغير جدول (@temp
). على الرغم من أن هذا قد يكون خطوات أكثر من مجرد كتابة عبارة create table
بنفسك ، إلا أنه يمنع الخطأ اليدوي مثل الأخطاء المطبعية وعدم تطابق نوع البيانات في العمليات الكبيرة. يمكن أن يستغرق تصحيح الأخطاء المطبعية وقتًا أطول من كتابة الاستعلام في المقام الأول.
هل يقوم الإجراء المخزن باسترداد البيانات فقط أو تعديلها أيضًا؟ إذا تم استخدامه فقط لاسترداد ، يمكنك تحويل الإجراء المخزن إلى دالة واستخدام تعبيرات الجدول الشائعة (CTEs) دون الحاجة إلى إعلان ذلك ، كما يلي:
with temp as (
select * from dbo.fnFunctionName(10, 20)
)
select col1, col2 from temp
ومع ذلك ، يجب استخدام كل ما يحتاج إلى استرداد من CTE في بيان واحد فقط. لا يمكنك عمل with temp as ...
ومحاولة استخدامه بعد بضعة أسطر من SQL. يمكنك الحصول على CTEs متعددة في عبارة واحدة لاستعلامات أكثر تعقيدًا.
فمثلا،
with temp1020 as (
select id from dbo.fnFunctionName(10, 20)
),
temp2030 as (
select id from dbo.fnFunctionName(20, 30)
)
select * from temp1020
where id not in (select id from temp2030)
وضعني كواسنوي معظم الطريق إلى هناك ، لكن كان هناك شيء واحد مفقود:
لذلك وجدت طريقة لتشغيل النظام وأيضًا لست مضطرًا لجعل تعريف الجدول جامدًا جدًا ، وإعادة تعريفه داخل إجراء مخزن آخر (وبالطبع اغتنم الفرصة التي قد يكسرها)!
نعم ، يمكنك إنشاء تعريف الجدول الذي تم إرجاعه من الإجراء المخزن بشكل حيوي باستخدام عبارة OPENQUERY مع متغيرات وهمية (طالما أن NO RESULT SET تُرجع نفس عدد الحقول وفي نفس موضع مجموعة البيانات مع البيانات الجيدة ).
بمجرد إنشاء الجدول ، يمكنك استخدام إجراء exec المخزن في الجدول المؤقت طوال اليوم.
EXEC sp_serveroption 'MYSERVERNAME', 'DATA ACCESS', TRUE
declare @locCompanyId varchar(8)
declare @locDateOne datetime
declare @locDateTwo datetime
set @locDateOne = '2/11/2010'
set @locDateTwo = getdate()
--Build temporary table (based on bogus variable values)
--because we just want the table definition and
--since openquery does not allow variable definitions...
--I am going to use bogus variables to get the table defintion.
select * into #tempCoAttendanceRpt20100211
FROM OPENQUERY(DBASESERVER,
'EXEC DATABASE.dbo.Proc_MyStoredProc 1,"2/1/2010","2/15/2010 3:00 pm"')
set @locCompanyId = '7753231'
insert into #tempCoAttendanceRpt20100211
EXEC DATABASE.dbo.Proc_MyStoredProc @locCompanyId,@locDateOne,@locDateTwo
set @locCompanyId = '9872231'
insert into #tempCoAttendanceRpt20100211
EXEC DATABASE.dbo.Proc_MyStoredProc @locCompanyId,@locDateOne,@locDateTwo
select * from #tempCoAttendanceRpt20100211
drop table #tempCoAttendanceRpt20100211
شكرًا على المعلومات التي تم توفيرها في الأصل ... نعم ، أخيرًا ، لست مضطرًا لإنشاء كل هذه العناصر الزائفة (صارمة) في جدول defintions عند استخدام بيانات من إجراء أو قاعدة بيانات مخزنة أخرى ، و نعم يمكنك استخدام المعلمات أيضا.
بحث العلامات المرجعية:
مزود 2005 الإجراء المخزن في جدول مؤقت
openquery مع الإجراء المخزن والمتغيرات 2005
openquery مع المتغيرات
تنفيذ الإجراء المخزن في جدول مؤقت
تحديث: هذا لن يعمل مع الجداول المؤقتة لذلك اضطررت إلى اللجوء لإنشاء الجدول المؤقت يدويًا.
إشعار Bummer : هذا لن يعمل مع الجداول المؤقتة ، http://www.sommarskog.se/share_data.html#OPENQUERY
المرجع: الشيء التالي هو تحديد LOCALSERVER. قد تبدو كلمة أساسية في المثال ، ولكنها في الحقيقة اسم فقط. هذا هو كيف نفعل ذلك:
sp_addlinkedserver @server = 'LOCALSERVER', @srvproduct = '',
@provider = 'SQLOLEDB', @datasrc = @@servername
لإنشاء خادم مرتبط ، يجب أن يكون لديك إذن ALTER أي خادم ، أو أن تكون عضوًا في أي من مسؤوليات خادم ثابت أو مسؤول النظام.
يفتح فتح اتصال جديد بـ SQL Server. هذا له بعض الآثار:
لا يمكن للإجراء الذي تتصل به مع OPENQUERY أن يشير إلى الجداول المؤقتة التي تم إنشاؤها في الاتصال الحالي.
يحتوي الاتصال الجديد على قاعدة البيانات الافتراضية الخاصة به (المعرفة باستخدام sp_addlinkedserver ، الافتراضي هو الرئيسي) ، لذلك يجب أن تتضمن كل مواصفات الكائن اسم قاعدة بيانات.
إذا كان لديك معاملة مفتوحة وتمسك بالأقفال عند الاتصال بـ OPENQUERY ، فلن يتمكن الإجراء الذي تم الاتصال به من الوصول إلى ما تقوم بقفله. هذا هو ، إذا لم تكن حذرا فسوف تمنع نفسك.
الاتصال غير مجاني ، لذلك هناك عقوبة أداء.
إذا كانت OPENROWSET تسبب لك مشكلات ، فهناك طريقة أخرى اعتبارًا من عام 2012 فصاعدًا ؛ الاستفادة من sys.dm_exec_describe_first_result_set_for_object ، كما هو مذكور هنا: استرداد أسماء الأعمدة وأنواع الإجراء المخزن؟
أولاً ، قم بإنشاء هذا الإجراء المخزن لإنشاء SQL المؤقتة
CREATE PROCEDURE dbo.usp_GetStoredProcTableDefinition(
@ProcedureName nvarchar(128),
@TableName nvarchar(128),
@SQL nvarchar(max) OUTPUT
)
AS
SET @SQL = 'CREATE TABLE ' + @tableName + ' ('
SELECT @SQL = @SQL + '['+name +'] '+ system_type_name +'' + ','
FROM sys.dm_exec_describe_first_result_set_for_object
(
OBJECT_ID(@ProcedureName),
NULL
);
--Remove trailing comma
SET @SQL = SUBSTRING(@SQL,0,LEN(@SQL))
SET @SQL = @SQL +')'
لاستخدام الإجراء ، اتصل به بالطريقة التالية:
DECLARE @SQL NVARCHAR(MAX)
exec dbo.usp_GetStoredProcTableDefinition
@ProcedureName='dbo.usp_YourProcedure',
@TableName='##YourGlobalTempTable',@SQL = @SQL OUTPUT
INSERT INTO ##YourGlobalTempTable
EXEC [dbo].usp_YourProcedure
select * from ##YourGlobalTempTable
لاحظ أنني أستخدم جدولًا عموميًا مؤقتًا. ذلك لأن استخدام EXEC لتشغيل SQL الديناميكي يخلق جلسة خاصة به ، وبالتالي فإن الجدول المؤقت العادي سيكون خارج نطاق أي رمز لاحق. إذا كان الجدول المؤقت العام يمثل مشكلة ، فأنت تستطيع تستخدم جدولًا مؤقتًا عاديًا ، ولكن يجب أن تكون أي SQL لاحقة ديناميكية ، أي ، يتم تنفيذها أيضًا بواسطة عبارة EXEC.
هذا proc المخزن يقوم بالمهمة:
CREATE PROCEDURE [dbo].[ExecIntoTable]
(
@tableName NVARCHAR(256),
@storedProcWithParameters NVARCHAR(MAX)
)
AS
BEGIN
DECLARE @driver VARCHAR(10)
DECLARE @connectionString NVARCHAR(600)
DECLARE @sql NVARCHAR(MAX)
DECLARE @rowsetSql NVARCHAR(MAX)
SET @driver = '''SQLNCLI'''
SET @connectionString =
'''server=' +
CAST(SERVERPROPERTY('ServerName') AS NVARCHAR(256)) +
COALESCE('\' + CAST(SERVERPROPERTY('InstanceName') AS NVARCHAR(256)), '') +
';trusted_connection=yes'''
SET @rowsetSql = '''EXEC ' + REPLACE(@storedProcWithParameters, '''', '''''') + ''''
SET @sql = '
SELECT
*
INTO
' + @tableName + '
FROM
OPENROWSET(' + @driver + ',' + @connectionString + ',' + @rowsetSql + ')'
EXEC (@sql)
END
GO
إنها إعادة صياغة بسيطة لهذا: إدراج نتائج الإجراء المخزن في الجدول بحيث يعمل بالفعل.
إذا كنت تريد أن تعمل مع جدول مؤقت ، فستحتاج إلى استخدام جدول ##GLOBAL
وإفلاته بعد ذلك.
إذا كنت محظوظًا بدرجة كافية لأن يكون لديك SQL 2012 أو أعلى ، فيمكنك استخدام dm_exec_describe_first_result_set_for_object
لقد قمت للتو بتحرير sql المقدمة من getqn. شكرا حصلت على.
يؤدي هذا إلى إنشاء جدول مؤقت عام بالاسم نفسه كاسم الإجراء. يمكن استخدام جدول درجة الحرارة لاحقًا كما هو مطلوب. فقط لا تنسى أن تسقطها قبل إعادة تنفيذها.
declare @procname nvarchar(255) = 'myProcedure',
@sql nvarchar(max)
set @sql = 'create table ##' + @procname + ' ('
begin
select @sql = @sql + '[' + r.name + '] ' + r.system_type_name + ','
from sys.procedures AS p
cross apply sys.dm_exec_describe_first_result_set_for_object(p.object_id, 0) AS r
where p.name = @procname
set @sql = substring(@sql,1,len(@sql)-1) + ')'
execute (@sql)
execute('insert ##' + @procname + ' exec ' + @procname)
end
الآن أعرف ما هي نتيجة الإجراء الذي أجريته ، لذلك أقوم بإجراء الاستعلام التالي.
CREATE TABLE [dbo].[tblTestingTree](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ParentId] [int] NULL,
[IsLeft] [bit] NULL,
[IsRight] [bit] NULL,
CONSTRAINT [PK_tblTestingTree] PRIMARY KEY CLUSTERED
(
[Id] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[tblTestingTree] ON
INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (1, NULL, NULL, NULL)
INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (2, 1, 1, NULL)
INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (3, 1, NULL, 1)
INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (4, 2, 1, NULL)
INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (5, 2, NULL, 1)
INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (6, 3, 1, NULL)
INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (7, 3, NULL, 1)
INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (8, 4, 1, NULL)
INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (9, 4, NULL, 1)
INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (10, 5, 1, NULL)
SET IDENTITY_INSERT [dbo].[tblTestingTree] OFF
القيم (10 ، 5 ، 1 ، NULL) SET IDENTITY_INSERT [dbo]. [tblTestingTree] في
create procedure GetDate
as
begin
select Id,ParentId from tblTestingTree
end
create table tbltemp
(
id int,
ParentId int
)
insert into tbltemp
exec GetDate
select * from tbltemp;
لإدراج مجموعة السجلات الأولى من الإجراء المخزن في جدول مؤقت ، يلزمك معرفة ما يلي:
sp_executesql
)قد يبدو ما سبق محدودًا ، لكن IMHO من المنطقي تمامًا - إذا كنت تستخدم sp_executesql
، فيمكنك مرة واحدة إرجاع عمودين ومرة واحدة وعشرة ، وإذا كان لديك مجموعات نتائج متعددة ، فلا يمكنك إدراجها في عدة جداول أيضًا - يمكنك إدراج الحد الأقصى في جدولين في عبارة T-SQL واحدة (باستخدام جملة OUTPUT
ولا توجد مشغلات).
لذلك ، فإن المشكلة هي بشكل أساسي كيفية تحديد بنية الجدول المؤقت قبل تنفيذ عبارة EXEC ... INTO ...
.
يعمل الأول مع OBJECT_ID
بينما يعمل الثاني والثالث مع استعلامات Ad-hoc أيضًا. أفضل استخدام DMV بدلاً من sp حيث يمكنك استخدام CROSS APPLY
وإنشاء تعريفات جدول مؤقت لإجراءات متعددة في نفس الوقت.
SELECT p.name, r.*
FROM sys.procedures AS p
CROSS APPLY sys.dm_exec_describe_first_result_set_for_object(p.object_id, 0) AS r;
أيضًا ، انتبه إلى حقل system_type_name
لأنه قد يكون مفيدًا للغاية. يخزن العمود تعريف كامل. فمثلا:
smalldatetime
nvarchar(max)
uniqueidentifier
nvarchar(1000)
real
smalldatetime
decimal(18,2)
ويمكنك استخدامه مباشرة في معظم الحالات لإنشاء تعريف الجدول.
لذلك ، أعتقد أنه في معظم الحالات (إذا كان الإجراء المخزن يتطابق مع معايير معينة) ، يمكنك بسهولة إنشاء عبارات ديناميكية لحل مثل هذه المشكلات (إنشاء جدول مؤقت ، وإدراج الإجراء المخزن الناتج عنه ، والقيام بما تحتاج إليه مع البيانات) .
لاحظ أن الكائنات المذكورة أعلاه تفشل في تحديد بيانات مجموعة النتائج الأولى في بعض الحالات مثل عند تنفيذ عبارات T-SQL الديناميكية أو استخدام الجداول المؤقتة في الإجراء المخزن.
إذا كان الاستعلام لا يحتوي على معلمة ، فاستخدم OpenQuery
وإلا استخدم OpenRowset
.
الشيء الأساسي هو إنشاء مخطط حسب الإجراء المخزن وإدراجه في هذا الجدول. على سبيل المثال:
DECLARE @abc TABLE(
RequisitionTypeSourceTypeID INT
, RequisitionTypeID INT
, RequisitionSourcingTypeID INT
, AutoDistOverride INT
, AllowManagerToWithdrawDistributedReq INT
, ResumeRequired INT
, WarnSupplierOnDNRReqSubmission INT
, MSPApprovalReqd INT
, EnableMSPSupplierCounterOffer INT
, RequireVendorToAcceptOffer INT
, UseCertification INT
, UseCompetency INT
, RequireRequisitionTemplate INT
, CreatedByID INT
, CreatedDate DATE
, ModifiedByID INT
, ModifiedDate DATE
, UseCandidateScheduledHours INT
, WeekEndingDayOfWeekID INT
, AllowAutoEnroll INT
)
INSERT INTO @abc
EXEC [dbo].[usp_MySp] 726,3
SELECT * FROM @abc
الشفرة
CREATE TABLE #T1
(
col1 INT NOT NULL,
col2 NCHAR(50) NOT NULL,
col3 TEXT NOT NULL,
col4 DATETIME NULL,
col5 NCHAR(50) NULL,
col6 CHAR(2) NULL,
col6 NCHAR(100) NULL,
col7 INT NULL,
col8 NCHAR(50) NULL,
col9 DATETIME NULL,
col10 DATETIME NULL
)
DECLARE @Para1 int
DECLARE @Para2 varchar(32)
DECLARE @Para3 varchar(100)
DECLARE @Para4 varchar(15)
DECLARE @Para5 varchar (12)
DECLARE @Para6 varchar(1)
DECLARE @Para7 varchar(1)
SET @Para1 = 1025
SET @Para2 = N'6as54fsd56f46sd4f65sd'
SET @Para3 = N'XXXX\UserName'
SET @Para4 = N'127.0.0.1'
SET @Para5 = N'XXXXXXX'
SET @Para6 = N'X'
SET @Para7 = N'X'
INSERT INTO #T1
(
col1,
col2,
col3,
col4,
col5,
col6,
col6,
col7,
col8,
col9,
col10,
)
EXEC [dbo].[usp_ProcedureName] @Para1, @Para2, @Para3, @Para4, @Para5, @Para6, @Para6
آمل أن يساعد هذا. يرجى التأهل حسب الاقتضاء.
لقد وجدت تمرير الصفائف/DataTables إلى إجراءات مخزنة والتي قد تعطيك فكرة أخرى حول كيفية حل مشكلتك.
يقترح الارتباط استخدام صورة نوع المعلمة لتمريرها إلى الإجراء المخزن. ثم في الإجراء المخزن ، يتم تحويل الصورة إلى متغير جدول يحتوي على البيانات الأصلية.
ربما هناك طريقة يمكن استخدامها مع جدول مؤقت.
لقد قابلت نفس المشكلة وهنا هو ما فعلته لهذا من اقتراح بول . الجزء الرئيسي هنا هو استخدام NEWID()
لتجنب قيام عدة مستخدمين بتشغيل إجراءات/نصوص المتجر في نفس الوقت ، ألم الجدول المؤقت العام.
DECLARE @sql varchar(max) = '',
@tmp_global_table varchar(255) = '##global_tmp_' + CONVERT(varchar(36), NEWID())
SET @sql = @sql + 'select * into [' + @tmp_global_table + '] from YOURTABLE'
EXEC(@sql)
EXEC('SELECT * FROM [' + @tmp_global_table + ']')
هناك طريقة أخرى تتمثل في إنشاء نوع واستخدام PIPELINED لإعادة تمرير الكائن. هذا يقتصر على معرفة الأعمدة ولكن. لكن لديها ميزة القدرة على القيام بما يلي:
SELECT *
FROM TABLE(CAST(f$my_functions('8028767') AS my_tab_type))
إذا كنت تعرف المعلمات التي يتم تمريرها وإذا لم يكن لديك حق الوصول إلى تكوين sp_configure ، فقم بتحرير الإجراء المخزن باستخدام هذه المعلمات ويمكن تخزينها في جدول عام ##.
إنها عملية بسيطة مكونة من خطوتين: - إنشاء جدول مؤقت - إدراج في الجدول المؤقت.
رمز لأداء نفسه:
CREATE TABLE #tempTable (Column1 int, Column2 varchar(max));
INSERT INTO #tempTable
EXEC [app].[Sproc_name]
@param1 = 1,
@param2 =2;
حسنًا ، يجب عليك إنشاء جدول مؤقت ، لكن ليس من الضروري أن يكون لديك المخطط الصحيح .... لقد قمت بإنشاء إجراء مخزن يقوم بتعديل جدول مؤقت موجود حتى يحتوي على الأعمدة المطلوبة مع البيانات الصحيحة الكتابة والترتيب (إسقاط جميع الأعمدة الموجودة ، إضافة أعمدة جديدة):
GO
create procedure #TempTableForSP(@tableId int, @procedureId int)
as
begin
declare @tableName varchar(max) = (select name
from tempdb.sys.tables
where object_id = @tableId
);
declare @tsql nvarchar(max);
declare @tempId nvarchar(max) = newid();
set @tsql = '
declare @drop nvarchar(max) = (select ''alter table tempdb.dbo.' + @tableName
+ ' drop column '' + quotename(c.name) + '';''+ char(10)
from tempdb.sys.columns c
where c.object_id = ' +
cast(@tableId as varchar(max)) + '
for xml path('''')
)
alter table tempdb.dbo.' + @tableName + ' add ' + QUOTENAME(@tempId) + ' int;
exec sp_executeSQL @drop;
declare @add nvarchar(max) = (
select ''alter table ' + @tableName
+ ' add '' + name
+ '' '' + system_type_name
+ case when d.is_nullable=1 then '' null '' else '''' end
+ char(10)
from sys.dm_exec_describe_first_result_set_for_object('
+ cast(@procedureId as varchar(max)) + ', 0) d
order by column_ordinal
for xml path(''''))
execute sp_executeSQL @add;
alter table ' + @tableName + ' drop column ' + quotename(@tempId) + ' ';
execute sp_executeSQL @tsql;
end
GO
create table #exampleTable (pk int);
declare @tableId int = object_Id('tempdb..#exampleTable')
declare @procedureId int = object_id('examplestoredProcedure')
exec #TempTableForSP @tableId, @procedureId;
insert into #exampleTable
exec examplestoredProcedure
ملاحظة لن ينجح ذلك إذا تعذر على sys.dm_exec_describe_first_result_set_for_object تحديد نتائج الإجراء المخزن (على سبيل المثال إذا كان يستخدم جدول مؤقت).