February 1, 2006 at 8:34 am
How to you assign the output from READTEXT into a variable?
I've tried SET and SELECT @var=READTEXT
and it throws an error
February 1, 2006 at 9:32 am
It throws an error because you cannot do this.
Text values greater than 8k cannot be stored in a page of memory therefor you cannot assin the value to a variable, because a variable cannot exceed the size of a page.
when managing text you have to place the text in memory and use a textpointer to manage the location of the data.
But in any case you cannot manage/manipulate text data in memory with t-sql.
Using Text columns requires alot of extra work. I have been luckily able to avoid using them. You have to evaluate if managing text/image data in a database is worth it.
Books Online:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/acdata/ac_8_qd_13_8orl.asp
February 1, 2006 at 9:42 am
Thanks Ray for replying
I already know BOL, and text pointers.
I used text because there was no alternative, and I need to manage very large code strings for later EXECute it.
I expect READTEXT to return short strings that could be placed in VARCHARS, and since I can see what's returned in the Query Analyzer, there should be some way to store it in a var.
Is this IMPOSSIBLE?
If so..... what's the REAL utility of readtext?!
February 1, 2006 at 9:48 am
I don't know, I was reading on MSDN when I looked up Readtext it notes that the readtext function is going away.
and the value you see in query analyzer is only the first 8000 characters.
Even microsoft doesn't use text when storing text for stored procedures. If you look at syscomments, this table is what holds the stored procedure definitions and such, and if you write a proc that is > 8000 characters, it actually saves 2 or more rows to hold all the characters.
So you may want to find an alternate way of storing these large strings.
Even then executing these strings using t-sql will be impossible. You will probably have to write an external api to read the text and execute it outside of sql server.
February 1, 2006 at 10:04 am
arrrg! I only need to catch a little piece from a text file!!!!
M$ really impresses me xDD ... they are stupid or what?
Why did they call a function READTEXT, if it doesn't read???
I swear I'll find a solution!
MS bastards... your are losing my precious time :>
February 1, 2006 at 11:16 am
I finally got it!
My solution is a bit bizarre, but sure works.
Tomorrow I'll post it.
C U!!!
February 1, 2006 at 2:10 pm
Why not to use simple SUBSTRING ?
You can use start > 8000 only length must be within 8000 (4000 for "N" types).
_____________
Code for TallyGenerator
February 2, 2006 at 1:51 am
thanks sergiy
I tried it, but can't get it working because I cannot declare any text variable inside a procedure
SET @v-2 = SUBSTRING( (SELECT Code FROM tmp_AuditTriggerCustomized)
, @StartPos
, @Lenght )
The text, ntext, and image data types are invalid in this subquery or aggregate expression.
February 2, 2006 at 2:15 am
Use CONVERT(varchar(256),text_field) AS First256Text, you can adjust the varchar size for the desired length.
Andy
February 2, 2006 at 2:20 am
Declare text vriable as a parameter of your SP.
_____________
Code for TallyGenerator
February 2, 2006 at 3:58 am
Declare the variable as varchar.
DECLARE @v-2 VARCHAR(8000)
SELECT @v-2 = SUBSTRING(Code,@StartPos, @Length) FROM tmp_AuditTriggerCustomised
You'll get an error if you give a length over 8000 (since the variable can't hold more than 8000 characters)
The restriction of varchars to 8000 has been removed in SQL 2005 and you can declare VARCHAR(max) which can hold up to 2^31-1 bytes
Note that READTEXT is deprecated and should not be used.
Is you've noticed, text fields are quite a pain to work with. Best avoided unless absolutely necessary
Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability
February 2, 2006 at 4:07 am
Author posted:
arrrg! I only need to catch a little piece from a text file!!!!
My solution absolutely fits this task.
_____________
Code for TallyGenerator
February 2, 2006 at 4:15 am
<sarcasm>Well excuse me for trying to help</sarcasm>
Just offerng an additional possibility that doesn't require adding an additional parameter to the procedure to deal with the output of substring.
Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability
February 3, 2006 at 5:43 am
Hi!
It's been some days since this thread.
I just liked to thank everybody who helped me upon a solution.
Sergiy, thanks for the SUBSTRING clue. As I said some days before I found a paralel solution, but finally ended using SUBSTRING function.
TKXXX!!!!
Well... as allways, I'll document the thread in case someone does a search over the same problem.
SET @STRING1 = (SELECT cast(SUBSTRING(TextFIELD1, 1, 8000) as varchar(8000)) FROM TABLE1)
SET @STRING2 = (SELECT cast(SUBSTRING(TextFIELD1, 8001, 8000) as varchar(8000)) FROM TABLE1)
PRINT @STRING1
PRINT @STRING2
EXECUTE (@STRING1 + @STRING2)
This was my bizarre solution
The problem is about to replace some code in brackets (<% %> from a full trigger stored in a text field.
This macro code in brackets will explode in a bigger common SQL code.
CREATE PROCEDURE sp_FindFirstBlock_Main @StartTag varchar(10) = '<%'
, @EndTag varchar(10) = '%>'
AS
DECLARE
@StartPos int
, @EndPos int
, @PtrText varbinary(16)
, @Lenght int
SET @StartPos = ( SELECT CHARINDEX(@StartTag, Code)-1 FROM tmp_AuditTriggerCustomized )
SET @EndPos = ( SELECT CHARINDEX(@EndTag, Code)-1 FROM tmp_AuditTriggerCustomized ) + LEN(@EndTag)
SET @PtrText = ( SELECT TEXTPTR(Code) FROM tmp_AuditTriggerCustomized )
SET @Lenght = @EndPos - @StartPos
READTEXT tmp_AuditTriggerCustomized.Code @PtrText
@StartPos
@Lenght
GO
CREATE PROCEDURE sp_FindFirstBlock @StartTag varchar(10) = '<%'
, @EndTag varchar(10) = '%>'
, @Block varchar(4000) OUTPUT
AS
CREATE TABLE #T1( MacroCode varchar(4000) )
INSERT INTO #T1
EXEC sp_FindFirstBlock_Main @StartTag, @EndTag
SET @Block = (SELECT TOP 1 MacroCode FROM #T1)
GO
So the call is ....
----REPLACE MACROS
SET @StartTag = '<%'
SET @EndTag = '%>'
--Seeks all the macro code blocks
EXEC sp_FindFirstBlock @StartTag, @EndTag, @Block = @CurrBlock OUTPUT
WHILE @CurrBlock <> ''
BEGIN
--Explode Macro code block
SET @SqlString = REPLACE( REPLACE(@CurrBlock, @StartTag, ''), @EndTag, '')--trim tags <% %>
SET @SqlString = N'Select @Out = ' + @SqlString
PRINT ' - [sp_CreateAuditTrigger] Macro Block: '
PRINT @SqlString
EXEC sp_executesql @SqlString
, N'@Out nvarchar(4000) OUTPUT'
, @Out = @NewText OUTPUT
SET @OldText = @CurrBlock
---- !! REPLACE !!
SET @PtrText = ( SELECT TEXTPTR(Code) FROM tmp_AuditTriggerCustomized )
SET @Len = LEN( @OldText )
SET @Pos = ( SELECT CHARINDEX(@OldText, Code)-1 FROM tmp_AuditTriggerCustomized )
WHILE @Pos <> -1
BEGIN
UPDATETEXT tmp_AuditTriggerCustomized.Code @PtrText
@Pos
@Len
@NewText
SET @Pos = ( SELECT CHARINDEX(@OldText, Code)-1 FROM tmp_AuditTriggerCustomized )
END
---- ¡¡ REPLACE ¡¡
EXEC sp_FindFirstBlock @StartTag, @EndTag, @Block = @CurrBlock OUTPUT
END
November 15, 2007 at 2:10 pm
I know this thread is going on 2 years old, however using it and other sources I have managed to cobble together a pretty decent solution for SQL 2000.
My problem was that I needed to send a bunch of T-SQL code from C#.NET to SQL Server 2000. Much as I wish we were on SQL 2005 and had varchar(Max) it wasn't an option. Since the amount of code frequently exceeded 8000 characters I needed to use an NText variable type. However, EXEC doesn't take an NText parameter. After trying many different ideas I finally decided to buckle and parse the NText parameter into a bunch of nvarchar parameters, string them together, and exec the whole thing.
Unfortunately you can't do much with an NText parameter so I created a temporary table and stuck it in there to play with it.
In my case the destination table was a global temporary table. Please don't flame me, I didn't write the original code and can't get permission to rewrite that part. However if you want to flame me for pointlessly using the Where clause when there is only one entry in the table, go for it 🙂
-- @sqlFromWhere is the NText input parameter
-- @sqlSelect is an nvarchar input parameter
-- @verbose is a bit input parameter
-- after creating a table and dumping the text into it I need to append a bit of SQL onto the front of it using UpdateText.
-- Create and populate the temporary table in one step
SELECT @sql = @sqlSelect + ' INTO ##input '
-- Manipulate, parse, and execute the text variable
Declare @ptrval binary(16), @iLength decimal, @iNum int, @iCount int, @iPlace int, @tmpSql nvarchar(4000), @iTmpLength int
Create Table #tblFromWhere(id int, statement ntext)
Insert Into [#tblFromWhere] ([id],[statement]) VALUES (1,@sqlFromWhere)
Select @ptrval = TEXTPTR([statement]) From [#tblFromWhere] Where [id] = 1
UpdateText #tblFromWhere.[statement] @ptrval 0 0 @sql
Select @iLength = DataLength([statement]) From [#tblFromWhere] Where [id] = 1
Set @iNum = Ceiling(@iLength/4000)
Set @iCount = 0
Set @tmpSql = ''
Set @sql = 'Exec ('
IF @verbose = 1 Begin
print 'Length of NText param: ' + Cast(@iLength as varchar(10))
print 'Num of loops required: ' + Cast(@iNum as varchar(10))
End
While @iCount < @iNum Begin
Set @iCount = @iCount + 1
Set @iPlace = (@iCount * 4000) - 4000 --+ 1
Set @iTmpLength = 4000
If @iCount = @iNum Begin Set @iTmpLength = @iLength-@iPlace End
Set @tmpSql = @tmpSql + 'Declare @StmntSeg' + Cast(@iCount as varchar(10)) + ' nvarchar(4000) '
Set @tmpSql = @tmpSql + 'Select @StmntSeg' + Cast(@iCount as varchar(10)) + ' = SubString([statement],'+Cast(@iPlace as varchar(20))+','+Cast(@iTmpLength as varchar(20))+') From #tblFromWhere Where [id] = 1 '
Set @sql = @sql + '@StmntSeg' + Cast(@iCount as varchar(10))
If @iCount < @iNum Begin Set @sql = @sql + '+' End
End
IF @verbose = 1 Begin
print '[Create and populate the temporary table in one step]'
SELECT @tmpSql + @sql + ')' AS [Create and populate the temporary table in one step]
print @tmpSql + @sql + ')'
End
EXEC (@tmpSql + @sql + ')')
-----------
I know the code is a pain to follow and I really don't expect anyone to look at it unless they are as desperate as I was. It should pretty much work out of the box for its intended purpose. Here is a look at what the output looks like...
Declare @StmntSeg1 nvarchar(4000)
Select @StmntSeg1 = SubString([statement],0,4000) From #tblFromWhere Where [id] = 1
Declare @StmntSeg2 nvarchar(4000)
Select @StmntSeg2 = SubString([statement],4000,4000) From #tblFromWhere Where [id] = 1
Declare @StmntSeg3 nvarchar(4000)
Select @StmntSeg3 = SubString([statement],8000,4000) From #tblFromWhere Where [id] = 1
Declare @StmntSeg4 nvarchar(4000)
Select @StmntSeg4 = SubString([statement],12000,3872) From #tblFromWhere Where [id] = 1
Exec (@StmntSeg1+@StmntSeg2+@StmntSeg3+@StmntSeg4)
On this run the NText parameter got broken into four separate pieces, then strung together and executed.
Viewing 15 posts - 1 through 14 (of 14 total)
You must be logged in to reply to this topic. Login to reply