1

我有一個存儲過程,將根據數據庫設置將某些動態sql轉換爲臨時表或視圖。這用於根據數據大小「調整」不同客戶端之間的數據庫功能,即臨時表需要更長的時間才能創建,但需要更長時間才能完成設置,視圖快速創建,但讀取時間稍長。選擇到內存優化表

我正在研究擴展它以包含內存優化表的一個選項,但無法看到如何使用內存優化表而無需首先聲明它。

我此刻的代碼將是一個格式,如:

SELECT TOP 10 * 
INTO FavoriteCustomers 
FROM Customers 
ORDER BY Spend DESC 

正如你可以看到我不聲明表,只用SELECT INTO。有什麼辦法可以選擇進入內存優化表?我可以使用:

sys.dm_exec_describe_first_result_set(@mySQLhere) 

這讓我對我通過在TSQL列定義,然後使用這些信息來預先創建表並插入到它,但我希望如果可能的話巧妙的方法。

有沒有人有任何解決方案?搜索只是讓我走上了如何將數據添加到MOT而非MOT創建中作爲選擇的一部分。

我知道這可能是不可能的,而且我確實有所描述的工作,我只是覺得我可能在這裏錯過了一個更好的選擇。

目前使用多個服務器,MOT功能僅在SQL2016上實現。

非常感謝提前。

+0

我正在尋找類似的嘗試,並強制執行查詢以某種順序而不會失去性能。我想他們會在這篇文章中提到這樣一個解決方案,即如果它存在,用內存優化表替換臨時表:https://docs.microsoft.com/en-us/sql/relational-databases/in-memory-oltp/更快的臨時表和表可變的使用內存優化 – user1378730

+1

我從來沒有找到一個很好的解決這個問題。我最終創建了表格,然後使用標準插入查詢。它工作正常。我將發佈我的代碼作爲答案。 –

回答

1
CREATE PROC [engine].[usp_CreateDynamicContent] 
    @ContentName AS NVARCHAR(MAX) 
, @NTS_SessionID NVARCHAR(MAX) 
, @SelectSQL NVARCHAR(MAX) 
, @PrimaryKeyField NVARCHAR(MAX) = NULL 
, @NonClusteredIndexField NVARCHAR(MAX) = NULL 
, @debug BIT = 0 
AS 
    BEGIN 

     DECLARE @ContentType AS NVARCHAR(MAX) 
     DECLARE @dcName AS NVARCHAR(MAX) 
     DECLARE @strSQL AS NVARCHAR(MAX) 

     SET @dcName = 'tmp.dc_' + @ContentName + '_' + @NTS_SessionID 

     IF OBJECT_ID(@dcName, 'V') IS NOT NULL /* Drop the view if it exists */ 
      BEGIN 
       SET @strSQL = 'DROP VIEW ' + @dcName 
       IF @debug = 1 
        PRINT (@strSQL) 
       EXEC (@strSQL) 
      END 

     IF OBJECT_ID(@dcName) IS NOT NULL /* Drop the table if it exists */ 
      BEGIN 
       SET @strSQL = 'DROP TABLE ' + @dcName 
       IF @debug = 1 
        PRINT (@strSQL) 
       EXEC (@strSQL) 
      END 

     /* This is my database listing types for each table. */ 
     SELECT @ContentType = ContentType 
     FROM guid.DynamicContents 
     WHERE ContentName = @ContentName 

     IF @ContentType = 'VIEW' 
      BEGIN 
       SET @strSQL = 'CREATE VIEW ' + @dcName + ' AS' + CHAR(13) + @SelectSQL 
       IF @debug = 1 
        PRINT (@strSQL) 
       EXEC (@strSQL) 
      END 
     ELSE 
      IF @ContentType IN ('TABLE', 'MOT') 
       BEGIN 
        SET @strSQL = '' 
        SELECT @strSQL = @strSQL + ',' + CHAR(10) + '[' + name + '] ' + system_type_name + CASE WHEN @PrimaryKeyField IS NOT NULL 
                                AND @ContentType = 'MOT' THEN ' NOT NULL PRIMARY KEY NONCLUSTERED' 
                              ELSE '' 
                             END + CHAR(13) 
        FROM sys.dm_exec_describe_first_result_set(@SelectSQL, NULL, 0) 
        SET @strSQL = STUFF(@strSQL, 1, 1, 'CREATE TABLE ' + @dcName + '(') 

        IF @PrimaryKeyField IS NOT NULL 
         AND @ContentType = 'TABLE' 
         BEGIN 
          SET @strSQL = @strSQL + CHAR(10) + ',CONSTRAINT pk_' + @ContentName + '_' + @NTS_SessionID + ' PRIMARY KEY (' + @PrimaryKeyField + ')' + CHAR(10) 
         END 

        SET @strSQL = @strSQL + ')' 
        IF @debug = 1 
         PRINT (@strSQL) 
        EXEC (@strSQL) 

        IF @NonClusteredIndexField IS NOT NULL 
         AND @ContentType = 'TABLE' 
         BEGIN 
          SET @strSQL = 'CREATE NONCLUSTERED INDEX ix_' + @ContentName + '_' + @NonClusteredIndexField + ' ON ' + @dcName + ' (' + @NonClusteredIndexField + ')' 
          IF @debug = 1 
           PRINT (@strSQL) 
          EXEC (@strSQL) 
         END 

        /* This section added in as I use cte's quite a lot */ 
        IF @SelectSQL LIKE '%/* INSERT HERE */%' 
         BEGIN 
          SET @strSQL = REPLACE(@SelectSQL, '/* INSERT HERE */', 'INSERT INTO ' + @dcName) 
         END 
        ELSE 
         BEGIN 
          SET @strSQL = 'INSERT INTO ' + @dcName + CHAR(13) + @SelectSQL 
         END 
        IF @debug = 1 
         PRINT (@strSQL) 
        EXEC (@strSQL) 
       END 

    END