it-swarm.asia

إدراج نتائج المخزن في جدول مؤقت

كيف أفعل 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".

لقد قرأت العديد من الأمثلة لإنشاء جدول مؤقت بنفس بنية الإجراء المخزن للإخراج ، والذي يعمل بشكل جيد ، ولكن سيكون من الجيد عدم توفير أي أعمدة.

1456
Ferdeen

يمكنك استخدام 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
666
Aaron Alton

إذا كنت تريد القيام بذلك دون الإعلان أولاً عن الجدول المؤقت ، فيمكنك محاولة إنشاء دالة معرفة من قبل المستخدم بدلاً من إجراء مخزن وجعل هذه الدالة المعرفة من قبل المستخدم تقوم بإرجاع جدول. بدلاً من ذلك ، إذا كنت تريد استخدام الإجراء المخزن ، فحاول إجراء شيء مثل هذا:

CREATE TABLE #tmpBus
(
   COL1 INT,
   COL2 INT
)

INSERT INTO #tmpBus
Exec SpGetRecords 'Params'
560
Gavin

في SQL Server 2005 ، يمكنك استخدام INSERT INTO ... EXEC لإدراج نتيجة الإجراء المخزن في جدول. من وثائق INSERT MSDN (لـ SQL Server 2000 ، في الواقع):

--INSERT...EXECUTE procedure example
INSERT author_sales EXECUTE get_author_sales
277
Matt Hamilton

هذه إجابة على نسخة معدلة قليلاً من سؤالك. إذا كان يمكنك التخلي عن استخدام إجراء مخزن لوظيفة معرفة من قبل المستخدم ، فيمكنك استخدام دالة معرفة من قبل المستخدم مضمنة في الجدول. هذا بشكل أساسي إجراء مخزن (سيستغرق معلمات) يقوم بإرجاع جدول كمجموعة نتائج ؛ وبالتالي سوف تضع بشكل جيد مع بيان 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 يحول دون استخدام الإجراءات المخزنة بإرجاع أكثر من مجموعة نتائج واحدة. يمكن أن يؤدي التفاف الوظائف المتعددة المعرفة من قبل المستخدم إلى جدول مضمّن في إجراء مخزن واحد إلى تحقيق ذلك.

182
Christian Loris
EXEC sp_serveroption 'YOURSERVERNAME', 'DATA ACCESS', TRUE

SELECT  *
INTO    #tmpTable
FROM    OPENQUERY(YOURSERVERNAME, 'EXEC db.schema.sproc 1')
117
Quassnoi

الحل الأسهل:

CREATE TABLE #temp (...);

INSERT INTO #temp
EXEC [sproc];

إذا كنت لا تعرف المخطط ، فيمكنك القيام بما يلي. يرجى ملاحظة أن هناك مخاطر أمنية شديدة في هذه الطريقة.

SELECT * 
INTO #temp
FROM OPENROWSET('SQLNCLI', 
                'Server=localhost;Trusted_Connection=yes;', 
                'EXEC [db].[schema].[sproc]')
113
Tigerjz32

عندما يقوم الإجراء المخزن بإرجاع الكثير من الأعمدة ولا ترغب في "إنشاء" جدول مؤقت يدويًا للاحتفاظ بالنتيجة ، فقد وجدت أن أسهل طريقة هي الانتقال إلى الإجراء المخزن وإضافة جملة "إلى" حدد آخر عبارة وأضف 1 = 0 إلى جملة أين.

تشغيل الإجراء المخزن مرة واحدة والعودة وإزالة رمز SQL الذي أضفته للتو. الآن ، سيكون لديك جدول فارغ يطابق نتيجة الإجراء المخزن. يمكنك إما "جدول نصي كإنشاء" لجدول مؤقت أو ببساطة إدراج مباشرة في هذا الجدول.

95
dotjoe
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;
62
nitin

إذا كان جدول نتائج 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 بنفسك ، إلا أنه يمنع الخطأ اليدوي مثل الأخطاء المطبعية وعدم تطابق نوع البيانات في العمليات الكبيرة. يمكن أن يستغرق تصحيح الأخطاء المطبعية وقتًا أطول من كتابة الاستعلام في المقام الأول.

44
FistOfFury

هل يقوم الإجراء المخزن باسترداد البيانات فقط أو تعديلها أيضًا؟ إذا تم استخدامه فقط لاسترداد ، يمكنك تحويل الإجراء المخزن إلى دالة واستخدام تعبيرات الجدول الشائعة (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)
44
Rashmi Pandit

وضعني كواسنوي معظم الطريق إلى هناك ، لكن كان هناك شيء واحد مفقود:

**** كنت بحاجة لاستخدام المعلمات في الإجراء المخزن. ****

و OPENQUERY لا يسمح بحدوث ذلك:

لذلك وجدت طريقة لتشغيل النظام وأيضًا لست مضطرًا لجعل تعريف الجدول جامدًا جدًا ، وإعادة تعريفه داخل إجراء مخزن آخر (وبالطبع اغتنم الفرصة التي قد يكسرها)!

نعم ، يمكنك إنشاء تعريف الجدول الذي تم إرجاعه من الإجراء المخزن بشكل حيوي باستخدام عبارة 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 ، فلن يتمكن الإجراء الذي تم الاتصال به من الوصول إلى ما تقوم بقفله. هذا هو ، إذا لم تكن حذرا فسوف تمنع نفسك.

الاتصال غير مجاني ، لذلك هناك عقوبة أداء.

28
Doug Lubey of Louisiana

إذا كانت 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.

25
StuartQ

هذا 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 وإفلاته بعد ذلك.

20
briantyler

إذا كنت محظوظًا بدرجة كافية لأن يكون لديك 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
17
Sandeep Gaadhe
  1. أقوم بإنشاء جدول به المخطط والبيانات التالية.
  2. إنشاء إجراء مخزن.
  3. الآن أعرف ما هي نتيجة الإجراء الذي أجريته ، لذلك أقوم بإجراء الاستعلام التالي.

    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;
    
15
Devansh

لإدراج مجموعة السجلات الأولى من الإجراء المخزن في جدول مؤقت ، يلزمك معرفة ما يلي:

  1. يمكن إدراج مجموعة الصف الأول فقط من الإجراء المخزن في جدول مؤقت
  2. لا يجب تنفيذ الإجراء المخزن عبارة T-SQL الحيوية (sp_executesql)
  3. تحتاج إلى تحديد بنية الجدول المؤقت أولاً

قد يبدو ما سبق محدودًا ، لكن 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 الديناميكية أو استخدام الجداول المؤقتة في الإجراء المخزن.

14
gotqn

إذا كان الاستعلام لا يحتوي على معلمة ، فاستخدم 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
12
ProblemSolver

الشفرة

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

آمل أن يساعد هذا. يرجى التأهل حسب الاقتضاء.

10
SoftwareARM

لقد وجدت تمرير الصفائف/DataTables إلى إجراءات مخزنة والتي قد تعطيك فكرة أخرى حول كيفية حل مشكلتك.

يقترح الارتباط استخدام صورة نوع المعلمة لتمريرها إلى الإجراء المخزن. ثم في الإجراء المخزن ، يتم تحويل الصورة إلى متغير جدول يحتوي على البيانات الأصلية.

ربما هناك طريقة يمكن استخدامها مع جدول مؤقت.

10
kevchadders

لقد قابلت نفس المشكلة وهنا هو ما فعلته لهذا من اقتراح بول . الجزء الرئيسي هنا هو استخدام 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 + ']')
9
zhongxiao37

هناك طريقة أخرى تتمثل في إنشاء نوع واستخدام PIPELINED لإعادة تمرير الكائن. هذا يقتصر على معرفة الأعمدة ولكن. لكن لديها ميزة القدرة على القيام بما يلي:

SELECT * 
FROM TABLE(CAST(f$my_functions('8028767') AS my_tab_type))
8
pierre

إذا كنت تعرف المعلمات التي يتم تمريرها وإذا لم يكن لديك حق الوصول إلى تكوين sp_configure ، فقم بتحرير الإجراء المخزن باستخدام هذه المعلمات ويمكن تخزينها في جدول عام ##.

3
lakshmivisalij

إنها عملية بسيطة مكونة من خطوتين: - إنشاء جدول مؤقت - إدراج في الجدول المؤقت.

رمز لأداء نفسه:

CREATE TABLE #tempTable (Column1 int, Column2 varchar(max));
INSERT INTO #tempTable 
EXEC [app].[Sproc_name]
@param1 = 1,
@param2 =2;
0
S Krishna

حسنًا ، يجب عليك إنشاء جدول مؤقت ، لكن ليس من الضروري أن يكون لديك المخطط الصحيح .... لقد قمت بإنشاء إجراء مخزن يقوم بتعديل جدول مؤقت موجود حتى يحتوي على الأعمدة المطلوبة مع البيانات الصحيحة الكتابة والترتيب (إسقاط جميع الأعمدة الموجودة ، إضافة أعمدة جديدة):

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 تحديد نتائج الإجراء المخزن (على سبيل المثال إذا كان يستخدم جدول مؤقت).

0
jmoreno