পরিবর্তনশীল হিসাবে সারণির নাম


171

আমি এই ক্যোয়ারীটি কার্যকর করার চেষ্টা করছি:

declare @tablename varchar(50)
set @tablename = 'test'
select * from @tablename

এটি নিম্নলিখিত ত্রুটি উত্পাদন করে:

এমএসজি 1087, স্তর 16, রাজ্য 1, লাইন 5

অবশ্যই টেবিলের পরিবর্তনশীল "@ টেবিলনাম" ঘোষণা করতে হবে।

টেবিলের নামটি গতিময়ভাবে পপুলেশন করার সঠিক উপায় কী?

উত্তর:


131

স্থির প্রশ্নাবলীর জন্য যেমন আপনার প্রশ্নের মতো, সারণীর নাম এবং কলামের নাম স্থিতিশীল হওয়া দরকার।

গতিশীল প্রশ্নের জন্য আপনার সম্পূর্ণ এসকিউএল গতিশীলভাবে উত্পন্ন করা উচিত এবং এটি সম্পাদন করতে sp_executesql ব্যবহার করা উচিত l

বিভিন্ন ডাটাবেসের একই টেবিলের মধ্যে ডেটা তুলনা করতে ব্যবহৃত স্ক্রিপ্টের একটি উদাহরণ এখানে রয়েছে:

স্থির প্রশ্ন:

SELECT * FROM [DB_ONE].[dbo].[ACTY]
EXCEPT
SELECT * FROM [DB_TWO].[dbo].[ACTY]

যেহেতু আমি সহজেই থের নাম পরিবর্তন করতে চাই tableএবং schemaআমি এই গতিশীল কোয়েরি তৈরি করেছি:

declare @schema varchar(50)
declare @table varchar(50)
declare @query nvarchar(500)

set @schema = 'dbo'
set @table = 'ACTY'

set @query = 'SELECT * FROM [DB_ONE].['+ @schema +'].[' + @table + '] EXCEPT SELECT * FROM [DB_TWO].['+ @schema +'].[' + @table + ']'

EXEC sp_executesql @query

যেহেতু গতিশীল ক্যোয়ারিতে অনেকগুলি বিশদ রয়েছে যা বিবেচনা করা দরকার এবং এগুলি মেন্টেন করা কঠিন আমি আপনাকে সুপারিশ করি যে আপনি পড়ুন: গতিশীল এসকিউএল এর অভিশাপ এবং আশীর্বাদ blessings


103

আপনার শেষ বক্তব্যটি এতে পরিবর্তন করুন:

EXEC('SELECT * FROM ' + @tablename)

আমি একটি স্টোরেড পদ্ধতিতে আমার এইভাবে করি। প্রথম ব্লকটি ভেরিয়েবলটি ঘোষণা করবে এবং বর্তমান বছর এবং মাসের নামের উপর ভিত্তি করে সারণীর নামটি সেট করবে, এই ক্ষেত্রে TEST_2012OCTOBER। আমি তখন এটি ডিবিতে ইতিমধ্যে উপস্থিত রয়েছে কিনা তা যাচাই করে নিই এবং এটি থাকলে তা সরিয়ে ফেলুন। তারপরে পরবর্তী ব্লকটি সারণীটি তৈরি করতে একটি পরামিতি বিবৃতি বিবরণ ব্যবহার করবে এবং পরামিতিগুলির সাথে অন্য টেবিলে রেকর্ড সহ এটি তৈরি করবে।

--DECLARE TABLE NAME VARIABLE DYNAMICALLY
DECLARE @table_name varchar(max)
SET @table_name = 
    (SELECT 'TEST_'
            + DATENAME(YEAR,GETDATE())
            + UPPER(DATENAME(MONTH,GETDATE())) )

--DROP THE TABLE IF IT ALREADY EXISTS
IF EXISTS(SELECT name 
          FROM sysobjects 
          WHERE name = @table_name AND xtype = 'U')

BEGIN
    EXEC('drop table ' +  @table_name)
END

--CREATES TABLE FROM DYNAMIC VARIABLE AND INSERTS ROWS FROM ANOTHER TABLE
EXEC('SELECT * INTO ' + @table_name + ' FROM dbo.MASTER WHERE STATUS_CD = ''A''')

এটি সেরা উত্তর।
কলিনম্যাক

এটি সর্বোত্তম উত্তর কারণ এটি ওপির বিদ্যমান কোডটিতে সর্বাধিক সরাসরি প্রযোজ্য।
বিএইচ

37

উত্তরের জন্য দেরি করে তবে অন্য কাউকে সাহায্য করা উচিত:

CREATE PROCEDURE [dbo].[GetByName]
    @TableName NVARCHAR(100)
    AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    DECLARE @sSQL nvarchar(500);

    SELECT @sSQL = N'SELECT * FROM' + QUOTENAME(@TableName);

    EXEC sp_executesql @sSQL



END

15
সুরক্ষার জন্য QUOTENAME গুরুত্বপূর্ণ। ধন্যবাদ।
সিহান ইয়াকার

3
কিন্তু এই জাতীয় কোয়েরি থেকে কীভাবে মূল্য ফেরানো যায়? যেমন COUNT(*)?
সানকাচার

35

আপনি একটি ভেরিয়েবলের জন্য কোনও টেবিলের নাম ব্যবহার করতে পারবেন না, পরিবর্তে আপনাকে এটি করতে হবে:

DECLARE @sqlCommand varchar(1000)
SET @sqlCommand = 'SELECT * from yourtable'
EXEC (@sqlCommand)


8

sp_executesqlযে কোনও এসকিউএল কার্যকর করতে ব্যবহার করুন , যেমন

DECLARE @tbl    sysname,
        @sql    nvarchar(4000),
        @params nvarchar(4000),
        @count  int

DECLARE tblcur CURSOR STATIC LOCAL FOR
   SELECT object_name(id) FROM syscolumns WHERE name = 'LastUpdated'
   ORDER  BY 1
OPEN tblcur

WHILE 1 = 1
BEGIN
   FETCH tblcur INTO @tbl
   IF @@fetch_status <> 0
      BREAK

   SELECT @sql =
   N' SELECT @cnt = COUNT(*) FROM dbo.' + quotename(@tbl) +
   N' WHERE LastUpdated BETWEEN @fromdate AND ' +
   N'                           coalesce(@todate, ''99991231'')'
   SELECT @params = N'@fromdate datetime, ' +
                    N'@todate   datetime = NULL, ' +
                    N'@cnt      int      OUTPUT'
   EXEC sp_executesql @sql, @params, '20060101', @cnt = @count OUTPUT

   PRINT @tbl + ': ' + convert(varchar(10), @count) + ' modified rows.'
END

DEALLOCATE tblcur

এই উদাহরণ খুব দরকারী।
ডাউনহিলসকি

0

এছাড়াও, আপনি এটি ব্যবহার করতে পারেন ...

DECLARE @SeqID varchar(150);
DECLARE @TableName varchar(150);  
SET @TableName = (Select TableName from Table);
SET @SeqID = 'SELECT NEXT VALUE FOR '+ @TableName + '_Data'
exec (@SeqID)

0
Declare  @tablename varchar(50) 
set @tablename = 'Your table Name' 
EXEC('select * from ' + @tablename)

1
স্ট্যাক ওভারফ্লোতে স্বাগতম! এই কোডটি কীভাবে এবং কেন এই সমস্যার সমাধান করে তার ব্যাখ্যা সহ প্রশ্নটি সমাধান করতে পারে যদিও আপনার পোস্টের গুণমান উন্নত করতে সত্যই সহায়তা করবে এবং সম্ভবত আরও বেশি ভোটের ফলাফল হবে। মনে রাখবেন যে আপনি ভবিষ্যতে পাঠকদের জন্য প্রশ্নের উত্তর দিচ্ছেন, কেবল এখনই জিজ্ঞাসা করা ব্যক্তি নয়। দয়া করে সম্পাদনা ব্যাখ্যা যোগ করতে পারেন এবং সীমাবদ্ধতা এবং অনুমানের কি প্রয়োগ একটি ইঙ্গিত দিতে আপনার উত্তর। পর্যালোচনা থেকে
ডাবল-বীপ

0

আপনার এসকিউএল সার্ভার গতিশীল এসকিউএল ব্যবহার করা উচিত

DECLARE @table     NVARCHAR(128),
        @sql       NVARCHAR(MAX);

SET @table = N'tableName';

SET @sql = N'SELECT * FROM ' + @table;

যে কোনও এসকিউএল কার্যকর করতে EXEC ব্যবহার করুন

EXEC (@sql)

যে কোনও এসকিউএল কার্যকর করতে EXEC sp_executesql ব্যবহার করুন

EXEC sp_executesql @sql;

যে কোনও এসকিউএল কার্যকর করতে EXECUTE sp_executesql ব্যবহার করুন

EXECUTE sp_executesql @sql

-1
Declare @fs_e int, @C_Tables CURSOR, @Table varchar(50)

SET @C_Tables = CURSOR FOR
        select name from sysobjects where OBJECTPROPERTY(id, N'IsUserTable') = 1 AND name like 'TR_%'
OPEN @C_Tables
FETCH @C_Tables INTO @Table
    SELECT @fs_e = sdec.fetch_Status FROM sys.dm_exec_cursors(0) as sdec where sdec.name = '@C_Tables'

WHILE ( @fs_e <> -1)
    BEGIN
        exec('Select * from '+ @Table)
        FETCH @C_Tables INTO @Table
        SELECT @fs_e = sdec.fetch_Status FROM sys.dm_exec_cursors(0) as sdec where sdec.name = '@C_Tables'
    END
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.