sql - एक अस्थायी तालिका में संग्रहीत प्रक्रिया के परिणाम डालें




sql-server sql-server-2005 tsql stored-procedures (21)

एक अस्थायी तालिका में संग्रहीत प्रक्रिया के पहले रिकॉर्ड सेट को सम्मिलित करने के लिए आपको निम्न को जानने की आवश्यकता है:

  1. संग्रहित प्रक्रिया का केवल पहला पंक्ति सेट अस्थायी तालिका में डाला जा सकता है
  2. संग्रहीत प्रक्रिया को गतिशील टी-एसक्यूएल कथन निष्पादित नहीं करना चाहिए ( sp_executesql )
  3. आपको पहले अस्थायी तालिका की संरचना को परिभाषित करने की आवश्यकता है

उपर्युक्त सीमा के रूप में देख सकता है, लेकिन IMHO यह पूरी तरह से समझ में आता है - यदि आप sp_executesql का उपयोग कर रहे हैं तो आप एक बार दो कॉलम लौटा सकते हैं और दस बार, और यदि आपके पास एकाधिक परिणाम सेट हैं, तो आप उन्हें कई तालिकाओं में भी सम्मिलित नहीं कर सकते - आप सम्मिलित कर सकते हैं एक टी-एसक्यूएल कथन में दो तालिका में अधिकतम ( OUTPUT खंड और कोई ट्रिगर्स का उपयोग नहीं)।

तो, मुद्दा मुख्य रूप से EXEC ... INTO ... प्रदर्शन करने से पहले अस्थायी तालिका संरचना को परिभाषित करने के लिए है EXEC ... INTO ... कथन।

OBJECT_ID साथ पहला काम जबकि दूसरा और तीसरा विज्ञापन-संबंधी प्रश्नों के साथ भी काम करता है। मैं एसपी के बजाय डीएमवी का उपयोग करना पसंद करता हूं क्योंकि आप 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 फ़ील्ड पर ध्यान system_type_name क्योंकि यह बहुत उपयोगी हो सकता है। यह स्तंभ पूर्ण परिभाषा को संग्रहीत करता है। उदाहरण के लिए:

smalldatetime
nvarchar(max)
uniqueidentifier
nvarchar(1000)
real
smalldatetime
decimal(18,2)

और आप तालिका परिभाषा बनाने के लिए ज्यादातर मामलों में सीधे इसका उपयोग कर सकते हैं।

इसलिए, मुझे लगता है कि ज्यादातर मामलों में (यदि संग्रहित प्रक्रिया कुछ मानदंडों से मेल खाती है) तो आप आसानी से ऐसे मुद्दों को हल करने के लिए गतिशील बयानों का निर्माण कर सकते हैं (अस्थायी तालिका बनाएं, इसमें संग्रहित प्रक्रिया परिणाम डालें, डेटा के साथ आपको जो चाहिए वह करें) ।

ध्यान दें, उपर्युक्त वस्तुएं कुछ cases में पहले परिणाम सेट डेटा को परिभाषित करने में असफल होती हैं जैसे कि जब गतिशील टी-एसक्यूएल कथन निष्पादित होते हैं या संग्रहीत प्रक्रिया में अस्थायी तालिकाओं का उपयोग किया जाता है।

मैं SELECT * INTO [temp table] FROM [stored procedure] एक SELECT * INTO [temp table] FROM [stored procedure] कैसे करूँ? FROM [Table] नहीं और [temp table] को परिभाषित किए बिना?

tmpBusLine से सभी डेटा का Select tmpBusLine ठीक काम करता है।

select *
into tmpBusLine
from BusinessLine

मैं वही कोशिश कर रहा हूं, लेकिन stored procedure का उपयोग कर डेटा लौटाता हूं, यह बिल्कुल समान नहीं है।

select *
into tmpBusLine
from
exec getBusinessLineHistory '16 Mar 2009'

आउटपुट संदेश:

संदेश 156, स्तर 15, राज्य 1, रेखा 2 कीवर्ड 'exec' के पास गलत वाक्यविन्यास।

मैंने आउटपुट संग्रहीत प्रक्रिया के रूप में एक ही संरचना के साथ एक अस्थायी तालिका बनाने के कई उदाहरण पढ़े हैं, जो ठीक काम करता है, लेकिन किसी भी कॉलम की आपूर्ति करना अच्छा होगा।


  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
    
    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
    

क्या आपकी संग्रहीत प्रक्रिया केवल डेटा पुनर्प्राप्त करती है या इसे संशोधित करती है? यदि इसका उपयोग केवल पुनर्प्राप्ति के लिए किया जाता है, तो आप संग्रहीत प्रक्रिया को फ़ंक्शन में परिवर्तित कर सकते हैं और सामान्य तालिका अभिव्यक्तियों (सीटीई) का उपयोग किए बिना इसे घोषित किए बिना कर सकते हैं:

with temp as (
    select * from dbo.fnFunctionName(10, 20)
)
select col1, col2 from temp

हालांकि, सीटीई से जो कुछ भी हासिल किया जाना चाहिए, उसे केवल एक कथन में इस्तेमाल किया जाना चाहिए। आप with temp as ... एक with temp as ... नहीं कर सकते with temp as ... और SQL की कुछ पंक्तियों के बाद इसका उपयोग करने का प्रयास करें। अधिक जटिल प्रश्नों के लिए आपके पास एक कथन में एकाधिक सीटीई हो सकते हैं।

उदाहरण के लिए,

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 उपयोग 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

यदि 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 को गतिशील होने की आवश्यकता होगी, जिसे EXEC कथन द्वारा भी निष्पादित किया जाता है।


यह आपके प्रश्न के थोड़ा संशोधित संस्करण का उत्तर है। यदि आप उपयोगकर्ता द्वारा परिभाषित फ़ंक्शन के लिए संग्रहीत प्रक्रिया के उपयोग को त्याग सकते हैं, तो आप इनलाइन तालिका-मूल्यवान उपयोगकर्ता-परिभाषित फ़ंक्शन का उपयोग कर सकते हैं। यह अनिवार्य रूप से एक संग्रहित प्रक्रिया है (पैरामीटर ले जाएगा) जो एक परिणाम सेट के रूप में एक टेबल देता है; और इसलिए एक आईएनटीओ कथन के साथ अच्छी तरह से जगह होगी।

यहां एक अच्छा त्वरित लेख है और अन्य उपयोगकर्ता परिभाषित कार्यों पर है। यदि आपके पास अभी भी संग्रहीत प्रक्रिया के लिए ड्राइविंग की आवश्यकता है, तो आप इनलाइन टेबल-मूल्यवान उपयोगकर्ता-परिभाषित फ़ंक्शन को संग्रहीत प्रक्रिया के साथ लपेट सकते हैं। संग्रहित प्रक्रिया केवल पैरामीटर को पास करती है जब यह इनलाइन तालिका-मूल्यवान उपयोगकर्ता-परिभाषित फ़ंक्शन से * चुनें।

तो उदाहरण के लिए, आपके पास एक विशेष क्षेत्र के लिए ग्राहकों की एक सूची प्राप्त करने के लिए एक इनलाइन टेबल-मूल्यवान उपयोगकर्ता परिभाषित फ़ंक्शन होगा:

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 फ़ंक्शन का उपयोग करने के लिए किया गया था (पुस्तकें ऑनलाइन से):

ओएलई डीबी डेटा स्रोत से दूरस्थ डेटा तक पहुंचने के लिए आवश्यक सभी कनेक्शन जानकारी शामिल है। यह विधि किसी लिंक किए गए सर्वर में तालिकाओं तक पहुंचने का एक विकल्प है और ओएलई डीबी का उपयोग कर रिमोट डेटा को जोड़ने और एक्सेस करने का एक बार, विज्ञापन की विधि है। ओएलई डीबी डेटा स्रोतों के अधिक लगातार संदर्भों के लिए, इसके बजाय लिंक किए गए सर्वर का उपयोग करें।

OPENROWSET का उपयोग करके काम पूरा हो जाएगा, लेकिन स्थानीय कनेक्शन खोलने और डेटा को मार्शल करने के लिए इसमें कुछ अतिरिक्त ओवरहेड लगेगा। यह सभी मामलों में भी एक विकल्प नहीं हो सकता है क्योंकि इसे किसी विज्ञापन की अनुमति की आवश्यकता होती है जो सुरक्षा जोखिम उत्पन्न करता है और इसलिए वांछित नहीं हो सकता है। इसके अलावा, OPENROWSET दृष्टिकोण एक से अधिक परिणाम सेट लौटने वाली संग्रहीत प्रक्रियाओं के उपयोग को रोक देगा। एक ही संग्रहीत प्रक्रिया में एकाधिक इनलाइन टेबल-वैल्यू उपयोगकर्ता-परिभाषित फ़ंक्शंस को लपेटना इसे प्राप्त कर सकता है।


I would do the following

  1. Create (convert SP to) a UDF (Table value UDF).

  2. select * into #tmpBusLine from dbo.UDF_getBusinessLineHistory '16 Mar 2009'


This can be done in SQL Server 2014+ provided SP only returns one table. If anyone finds a way of doing this for multiple tables I'd love to know about it.

DECLARE @storeProcname NVARCHAR(MAX) = ''

SET @storeProcname = 'myStoredProc'

DECLARE @strSQL AS VARCHAR(MAX) = 'CREATE TABLE myTableName '

SELECT @strSQL = @strSQL+STUFF((
SELECT ',' +name+' ' + system_type_name 
FROM sys.dm_exec_describe_first_result_set_for_object (OBJECT_ID(@storeProcname),0)
FOR XML PATH('')
),1,1,'(') + ')'

EXEC (@strSQL)

INSERT INTO myTableName
EXEC ('myStoredProc @param1=1, @param2=2')

SELECT * FROM myTableName

DROP TABLE myTableName

This pulls the definition of the returned table from system tables, and uses that to build the temp table for you. You can then populate it from the SP as stated before.

There are also variants of this that work with Dynamic SQL too.


SQL सर्वर 2005 में आप एक तालिका में संग्रहीत प्रक्रिया के परिणाम डालने के लिए INSERT INTO ... EXEC का उपयोग कर सकते हैं। एमएसडीएन के INSERT दस्तावेज से (वास्तव में SQL सर्वर 2000 के लिए):

--INSERT...EXECUTE procedure example
INSERT author_sales EXECUTE get_author_sales

यह संग्रहीत 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 तालिका का उपयोग करने और बाद में इसे छोड़ने की आवश्यकता होगी।


सबसे आसान समाधान:

CREATE TABLE #temp (...);

INSERT INTO #temp
EXEC [sproc];

यदि आप स्कीमा नहीं जानते हैं तो आप निम्न कार्य कर सकते हैं। कृपया ध्यान दें कि इस विधि में गंभीर सुरक्षा जोखिम हैं।

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

Quassnoi मुझे सबसे अधिक रास्ता वहाँ रखा, लेकिन एक बात गायब थी:

**** मुझे संग्रहीत प्रक्रिया में पैरामीटर का उपयोग करने की आवश्यकता है। ****

और OPENQUERY इस होने की अनुमति नहीं देता है:

इसलिए मुझे सिस्टम को काम करने का एक तरीका मिला और तालिका परिभाषा को इतना कठोर बनाने की ज़रूरत नहीं है, और इसे किसी अन्य संग्रहीत प्रक्रिया के अंदर फिर से परिभाषित करना है (और निश्चित रूप से इसे तोड़ने का मौका लें)!

हां, आप गतिशील रूप से संग्रहित प्रक्रिया से लौटाई गई तालिका परिभाषा को बोगस varaiables के साथ OPENQUERY कथन का उपयोग करके (जब तक कोई परिणाम SET फ़ील्ड की संख्या और अच्छे डेटा वाले डेटासेट के समान स्थिति में) लौटाता है।

एक बार टेबल बनने के बाद, आप पूरे दिन अस्थायी तालिका में निष्पादित प्रक्रिया का उपयोग कर सकते हैं।

और नोट करने के लिए (ऊपर बताए गए अनुसार) आपको डेटा एक्सेस सक्षम करना होगा,

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

मूल रूप से प्रदान की गई जानकारी के लिए धन्यवाद ... हां, आखिरकार मुझे किसी अन्य संग्रहीत प्रक्रिया या डेटाबेस से डेटा का उपयोग करते समय इन सभी बोगस (सख्त) तालिका परिभाषाएं बनाने की ज़रूरत नहीं है , और हाँ आप पैरामीटर का भी उपयोग कर सकते हैं।

खोज संदर्भ टैग:

  • SQL तालिका संग्रहीत प्रक्रिया temp तालिका में

  • संग्रहीत प्रक्रिया और चर 2005 के साथ openquery

  • चर के साथ openquery

  • अस्थायी प्रक्रिया को अस्थायी तालिका में निष्पादित करें

अपडेट करें: यह अस्थायी तालिकाओं के साथ काम नहीं करेगा इसलिए मुझे अस्थायी तालिका मैन्युअल रूप से बनाने का सहारा लेना पड़ा।

बमर नोटिस : यह अस्थायी तालिकाओं के साथ काम नहीं करेगा, http://www.sommarskog.se/share_data.html#OPENQUERY

संदर्भ: अगली बात LOCALSERVER को परिभाषित करना है। यह उदाहरण में एक कीवर्ड की तरह लग सकता है, लेकिन वास्तव में यह केवल एक नाम है। इसे आपको इसी तरह करना होगा:

sp_addlinkedserver @server = 'LOCALSERVER',  @srvproduct = '',
                   @provider = 'SQLOLEDB', @datasrc = @@servername

एक लिंक किए गए सर्वर को बनाने के लिए, आपके पास किसी भी सर्वर के भीतर अनुमति होनी चाहिए, या किसी भी निश्चित सर्वर भूमिका sysadmin या setupadmin का सदस्य होना चाहिए।

OPENQUERY SQL सर्वर के लिए एक नया कनेक्शन खोलता है। इसमें कुछ प्रभाव हैं:

OPENQUERY के साथ आप जिस प्रक्रिया को कॉल करते हैं वह वर्तमान कनेक्शन में बनाए गए अस्थायी तालिकाओं को संदर्भित नहीं कर सकता है।

नए कनेक्शन का अपना डिफ़ॉल्ट डेटाबेस है (sp_addlinkedserver के साथ परिभाषित, डिफ़ॉल्ट मास्टर है), इसलिए सभी ऑब्जेक्ट विनिर्देशों में डेटाबेस नाम शामिल होना चाहिए।

यदि आपके पास ओपन ट्रांज़ेक्शन है और आप ओपनक्वरी कॉल करते समय लॉक धारण कर रहे हैं, तो कॉल की गई प्रक्रिया आपके द्वारा लॉक किए जाने वाले एक्सेस तक नहीं पहुंच सकती है। यही है, अगर आप सावधान नहीं हैं तो आप खुद को अवरुद्ध कर देंगे।

कनेक्टिंग मुफ्त में नहीं है, इसलिए एक प्रदर्शन जुर्माना है।


यदि आप SQL 2012 या उच्चतर के लिए भाग्यशाली हैं, तो आप dm_exec_describe_first_result_set_for_object उपयोग कर सकते हैं

मैंने अभी gotqn द्वारा प्रदान की गई एसक्यूएल संपादित की है। धन्यवाद gotqn।

यह प्रक्रिया नाम के समान नाम के साथ एक वैश्विक अस्थायी तालिका बनाता है। बाद में अस्थायी तालिका का उपयोग किया जा सकता है। पुनः निष्पादन से पहले इसे छोड़ना न भूलें।

    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 #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

आशा है कि ये आपकी मदद करेगा। कृपया उपयुक्त के रूप में योग्यता प्राप्त करें।


आप इसके लिए OPENROWSET उपयोग कर सकते हैं। एक नज़र देख लो। यदि विज्ञापन पहले से सक्षम नहीं है, तो मैंने विज्ञापन वितरित क्वेरीज़ को सक्षम करने के लिए sp_configure कोड भी शामिल किया है।

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

मुझे संग्रहित प्रक्रियाओं में पासिंग Arrays / DataTables मिलते हैं जो आपको एक और विचार दे सकते हैं कि आप अपनी समस्या को कैसे हल कर सकते हैं।

लिंक संग्रहीत प्रक्रिया में पास करने के लिए एक छवि प्रकार पैरामीटर का उपयोग करने का सुझाव देता है। फिर संग्रहीत प्रक्रिया में, छवि को मूल डेटा वाले तालिका चर में बदल दिया जाता है।

हो सकता है कि एक अस्थायी तालिका के साथ इसका उपयोग किया जा सके।


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;

I met the same problem and here is what I did for this from Paul's suggestion . The main part is here is to use NEWID() to avoid multiple users run the store procedures/scripts at the same time, the pain for global temporary table.

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 + ']')

जब संग्रहीत प्रक्रिया बहुत सारे कॉलम लौटाती है और आप परिणाम को पकड़ने के लिए मैन्युअल रूप से "अस्थायी तालिका" बनाना नहीं चाहते हैं, तो मुझे संग्रहीत प्रक्रिया में जाने का सबसे आसान तरीका मिल गया है और "इन" खंड को जोड़ना है अंतिम चयन कथन और जहां खंड पर 1 = 0 जोड़ें।

संग्रहीत प्रक्रिया को एक बार चलाएं और वापस जाएं और आपके द्वारा अभी जोड़े गए SQL कोड को हटा दें। अब, आपके पास संग्रहित प्रक्रिया के परिणाम से मेल खाने वाली एक खाली तालिका होगी। आप एक अस्थायी तालिका के लिए या तो "स्क्रिप्ट टेबल बनाने के लिए" या बस उस तालिका में सीधे डालें।


यदि आपकी संग्रहित प्रो की परिणाम तालिका हाथ से "तालिका बनाएं" कथन टाइप करने के लिए बहुत जटिल है, और आप OPENQUERY या OPENROWSET का उपयोग नहीं कर सकते हैं, तो आप कॉलम और डेटा प्रकारों की सूची जेनरेट करने के लिए sp_help का उपयोग कर सकते हैं। एक बार आपके पास कॉलम की सूची हो जाने के बाद, यह आपकी आवश्यकताओं के अनुसार इसे फ़ॉर्मेट करने का मामला है।

चरण 1: आउटपुट क्वेरी में "#temp" जोड़ें (उदाहरण के लिए "[...] में #temp में चुनें [...]")।

सबसे आसान तरीका सीधे proc में आउटपुट क्वेरी को संपादित करना है। अगर आप संग्रहीत प्रोसेस को नहीं बदल सकते हैं, तो आप सामग्री को एक नई क्वेरी विंडो में कॉपी कर सकते हैं और वहां क्वेरी को संशोधित कर सकते हैं।

चरण 2: temp तालिका पर sp_help चलाएं। (उदाहरण के लिए "exec tempdb..sp_help #temp")

अस्थायी तालिका बनाने के बाद, वर्चर्स फ़ील्ड के आकार सहित कॉलम और डेटा प्रकारों की एक सूची प्राप्त करने के लिए temp तालिका पर sp_help चलाएं।

चरण 3: डेटा कॉलम और प्रकारों को एक तालिका तालिका विवरण में कॉपी करें

मेरे पास एक एक्सेल शीट है जिसका उपयोग मैं sp_help के आउटपुट को "तालिका बनाएं" कथन में प्रारूपित करने के लिए करता हूं। आपको उस फैंसी की ज़रूरत नहीं है, बस अपने एसक्यूएल एडिटर में कॉपी और पेस्ट करें। "तालिका #x [...]" या "@x तालिका घोषित करें [...]" कथन बनाने के लिए कॉलम नाम, आकार और प्रकार का उपयोग करें, जिसे आप संग्रहीत प्रक्रिया के परिणामों को INSERT में उपयोग करने के लिए उपयोग कर सकते हैं।

चरण 4: नव निर्मित तालिका में डालें

अब आपके पास एक प्रश्न होगा जो इस धागे में वर्णित अन्य समाधानों की तरह है।

DECLARE @t TABLE 
(
   --these columns were copied from sp_help
   COL1 INT,
   COL2 INT   
)

INSERT INTO @t 
Exec spMyProc 

इस तकनीक का उपयोग एक temp तालिका ( #temp ) को तालिका चर ( @temp ) में कनवर्ट करने के लिए भी किया जा सकता है। हालांकि यह स्वयं create table विवरण लिखने से अधिक कदम हो सकता है, यह बड़ी प्रक्रियाओं में टाइपोज़ और डेटा प्रकार के विसंगतियों जैसे मैन्युअल त्रुटि को रोकता है। एक टाइपो को डिबग करने से क्वेरी को पहले स्थान पर लिखने में अधिक समय लग सकता है।


इसे इस्तेमाल करे

SELECT COLUMNS.*
FROM   INFORMATION_SCHEMA.COLUMNS COLUMNS,
       INFORMATION_SCHEMA.TABLES TABLES
WHERE  COLUMNS.TABLE_NAME = TABLES.TABLE_NAME
       AND Upper(COLUMNS.COLUMN_NAME) = Upper('column_name') 




sql sql-server sql-server-2005 tsql stored-procedures