Link to home
Start Free TrialLog in
Avatar of LenTompkins
LenTompkinsFlag for United States of America

asked on

Using Local variable Nvarchar(max)

I created  a routine to dynamically create tables in my current database from the structure found in another database.  I originally created it on my local machine and it works perfectly.  Then I went to a customer's machine who is also using SQL Server 2008, but only has 4 gigs in memory, and had problems.  

when I set the local variable  to nvarchar(max)  or nvarchar(4000)
The create statement is truncated

When I set the local variable to nvarchar(2000)
the statement creates properly for selected tables that do not have many columns

Why is this happening?  

Second question:  I also moved this procedure to a machine that has sql 2005 installed and I ran the proc to see what problems I would get.  The code works fine for all tables except two where the table structure is longer than 4000 bytes.  
Is there a way to get around this problem?  
I tried showing the len(@vsSQL) and for tables that created properly some of the lengths were over 4000 bytes and for the two tables that have problems, the length is over 4000, but not as long as a few tables that created properly.  Obviously, I can't depend on this count.  
Here is the code:
   declare @vsSQL nvarchar(max)
      declare @execsql nvarchar(max)
      declare @vsInsertSQL nvarchar(max)
      declare @vsTableName varchar(50)
      declare @cprdbName varchar(100), @dbName varchar(100)
      declare @serverName varchar(100), @primComp int

      set @primComp = (Select PrimaryComp from InitialSetup)

      set @dbName = (Select DatabaseName from Specifics where SiteNO = @primComp)
      --  Step 1 set database to bulk logged
      Select @execsql = 'Alter Database ' + @dbName + '  Set recovery Bulk_Logged;' + CHAR(10)
      --Print @execSQL
      execute sp_executesql @execSQL
      

      --  Step 2 determine location of the Production server name
      set @cprdbName = (Select ProductionCPRLocation from Specifics where SiteNO = @primComp)
      set @serverName = (Select ProductionServerName from Specifics where SiteNO = @primComp)
      --  Step 3 if the linked server name does not exist, add it using dynamic name
      Select @execsql = 'if  not exists(Select srvname from master.dbo.sysservers where srvname = ''' + @serverName + ''')' + CHAR(10) +
                  'begin       exec sp_addlinkedserver @server=''' + @serverName + '''  end'
      --Print @execSQL
      execute sp_executesql @execSQL

      -- Step 4 Create Synonyms for objects int the production database name
      Select @execsql = 'Create synonym dbObjects for [' + @serverName + '].' + @cprdbName + '.sys.objects'
       --Print @execSQL
      execute sp_executesql @execSQL
      Select @execsql = 'Create synonym dbColumns for [' + @serverName + '].' + @cprdbName + '.sys.Columns'
      --Print @execSQL
      execute sp_executesql @execSQL
      Select @execsql = 'Create synonym dbType for [' + @serverName + '].' + @cprdbName + '.sys.Types'
      --Print @execSQL
      execute sp_executesql @execSQL
      Select @execsql = 'Create synonym dbIndexes for [' + @serverName + '].' + @cprdbName + '.sys.indexes'
      --Print @execSQL
      execute sp_executesql @execSQL
      Select @execsql = 'Create synonym dbIndexCol for [' + @serverName + '].' + @cprdbName + '.sys.index_columns'
      --Print @execSQL
      execute sp_executesql @execSQL

----------------------------------------------------------------------------------------------------------------

      -- Step 6 generate Create table statements from production database
      Declare TCursor2 Cursor for Select TableName from CopyTables
      Open TCursor2
      Fetch TCursor2 into @vsTableName
      while @@FETCH_STATUS = 0
      begin
            
        --  Step 2 generate Create table statements from CPR7 database
        
        select @vsSQL = 'CREATE TABLE ' + @vsTableName +  ' ('
      
            select @vsSQL = @vsSQL +  sc.Name + ' ' +
            st.Name +
             case when st.Name in ('varchar','nvarchar','char','nchar') then '(' + cast(sc.max_length as varchar) + ') '
                    when st.name in ('numeric', 'decimal') then  '(' + CAST(sc.precision as varchar) + ',' + CAST(sc.scale as varchar) + ') '
                    else ' ' end
                    +
            case when sc.is_nullable = 1 then 'NULL' else 'NOT NULL' end + ','
            from dbObjects so
            join dbColumns sc on sc.object_id = so.object_id
            join dbType st on st.user_type_id = sc.user_type_id
             
            where so.name = @vsTableName
            order by  sc.column_id
             
             --    add Primary key constraint
             Select   @vsSQL = @vsSQL + 'Constraint [' + si.name + '2'  + '] PRIMARY KEY CLUSTERED ( '
             from dbObjects so
             join dbIndexes si
             on so.object_id = si.object_id and si.type_desc = 'CLUSTERED'
             where so.name = @vsTableName
             
            --  add Primary key columns
            Select   @vsSQL = @vsSQL + sc.name + case when sic.is_descending_key = 0 then ' ASC,  ' else ' DESC,  '  end
            from dbObjects so
             join dbIndexes si
             on so.object_id = si.object_id  and si.type_desc = 'CLUSTERED'
             join dbColumns sc
             on sc.object_id = so.object_id
             join dbIndexCol sic
             on sc.object_id = sic.object_id and sc.column_id = index_column_id and si.index_id = sic.index_id
             where so.name = @vsTableName
             order by key_ordinal



            select @execSQL = substring(@vsSQL,1,len(@vsSQL) - 1)  + '))'  
            Select @vsInsertSQL = Len(@vsSQL)
            Print @vsInsertSQL
            Print @execSQL
        
        execute sp_executesql @execSQL
          
        fetch next from TCursor2 into  @vsTableName  
      end
      Close TCursor2
      Deallocate TCursor2


------------------------------------------------------------------------------------------
      -- Step 7 Insert all rows from Productions version into cPR_Reporting

      Declare TCursor3 Cursor for Select TableName from CopyTables where tablename not in ('LineItemLinks', 'LineItemsAssigned')
      Open TCursor3
      Fetch TCursor3 into @vsTableName
      while @@FETCH_STATUS = 0
      begin
        -- Step 3 Insert all rows from Productions version into cPR_Reporting
            select @vsInsertSQL = 'INSERT INTO ' + @vsTableName  + ' (' + char(10)
      
            select @vsInsertSQL = @vsInsertSQL + ' ' + sc.Name + ','
             from dbObjects so
             join dbColumns sc on sc.object_id = so.object_id
             join dbType st on st.user_type_id = sc.user_type_id
             where so.name = @vsTableName
             order by
             sc.column_id

            select @vsInsertSQL = substring(@vsInsertSQL,1,len(@vsInsertSQL) - 1)  + ')' + char(10) + 'Select '
            select @vsInsertSQL = @vsInsertSQL + ' ' + sc.Name + ','
             from dbObjects so
             join dbColumns sc on sc.object_id = so.object_id
             join dbType st on st.user_type_id = sc.user_type_id
             where so.name = @vsTableName
             order by
             sc.column_id
             
             
             select @execSQL = substring(@vsInsertSQL,1,len(@vsInsertSQL) - 1) + char(10) + 'from [' +
                    @ServerName + '].' + @cprdbName + '.dbo.' + @vsTableName + CHAR(10)
             Print @execSQL
             execute sp_executesql @execSQL
        
        fetch next from TCursor3 into  @vsTableName  
      end
      Close TCursor3
      Deallocate TCursor3

      -- Step 8 drop synonyms
      DROP SYNONYM dbObjects
      Drop Synonym dbColumns
      Drop synonym dbType
      Drop synonym dbIndexes
      Drop synonym dbIndexCol
      
      -- Step 9 Alter database
      Select @execsql = 'Alter Database ' + @dbName + '  Set recovery simple;' + CHAR(10)
      -- Print @execSQL
      execute sp_executesql @execSQL


Any thoughts would be greatly appreciated.
Avatar of venk_r
venk_r
Flag of United States of America image

Are you selecting it, or executing it somewhere, or what?

SQL Server Management Studio defaults to only presenting a small amount of text that you select all at once. If you want to increase it, it's in Tools - Options - Query Results. It'll display more, up to 65,535 characters, if you tell it to.

Is that what you're running into?
Avatar of LenTompkins

ASKER

No,  If I have the local variable set to nvarchar(2000)
the create statement is perfect:
CREATE TABLE ADJTYPE (CPK_ADJTYPE int NOT NULL,TEXT_ varchar(20) NULL,CODE varchar(5) NULL,GLACCT varchar(20) NULL,GLDEPT varchar(10) NULL,DELFLAG int NOT NULL,TOUCHDATE datetime NULL,CHGBYHOST varchar(100) NULL,CREATEDON datetime NULL,CREATEDBY varchar(100) NULL,Constraint [CN__ADJTYPE_CPK_ADJTYPE2] PRIMARY KEY CLUSTERED ( CPK_ADJTYPE ASC))

if I have the local variable set to nvarchar(max)
the create statement is:
CREATE TABLE ADJTYPE (CREATEDBY varchar(100) NULL,Constraint [CN__ADJTYPE_CPK_ADJTYPE2] PRIMARY KEY CLUSTERED ( CPK_ADJTYPE ASC))

is there a setting in this version of SQL server that needs to be changed?
I also want you to know that the database is set to a compatability of sql 2005 even though the machine is SQL 2008.
Can you tell me the value by going to
SQL Server Management Studio Tools - Options - Query Results-SQL Server-Results to Text-Maximum number of characters displayed in each column ?
The maximum number of characters displayed in each column is 256
I changed it to 1000 and it had no effect on the query it generated.  It was still truncated.
I think there is some limitation with print command w.r.t nvarchar datatype

Some potential workarounds, but they might not fit your situation:

•add some logic to test the length of the variable and split into manageable chunks of 8000 or less varchars, and PRINT each one

•set 'Results to Text' and use select @x intead of using print command
I looked at the Results to Text and it was changed to 8192.  Then I ran the query with Select @vsSQL instead of Print @vsSQL and I set the local variables to nvarchar(3900) and it runs properly.  
I changed the local variable to nvarchar(4000 )and the results are incorrect.
we are missing a number of columns.
CREATE TABLE ADJTYPE (CREATEDBY varchar(100) NULL,Constraint [CN__ADJTYPE_CPK_ADJTYPE2] PRIMARY KEY CLUSTERED ( CPK_ADJTYPE ASC))
SOLUTION
Avatar of venk_r
venk_r
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you for your assistance.  I tried setting all of the local variables before using any of them, and it didn't change the results.  I am thinking that I will change the way I create the statement.  I will set the size to 3900 and then determine how many rows are in the table.  If the number of rows exceeds a number I have yet to determine, I can generate the create statement for the first X columns to one local variable set to 3900 and then select the additional columns and the primary key to another local variable and then concatenate and execute them.  
If you have a better idea, I'd be glad to hear it.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I appreciate your continued response to my  problem