October 26, 2003

BLOBS and CF

A question popped up on Macromedia's forums regarding row size in MS SQL server. There is a max of 8072, which was hit with a nvarchar of 4000.

To solve this problem, the user was going to use an nText datatype and limit the size to 4000 using JS.

My thoughts are if the users of the system are writing more the 4000 bytes of info, why not use it? The text and ntext data types can store and retrieve fields up to 2GB. The CF Administrator blob default byte setting is 65000. (With MX make sure the Blob data type is check in the DSN settings) All that is stored in the SQL server Blob column is a 16-byte pointer to the first page of the column's page chain.

The best way to handle the insert is with the WRITETEXT command.

WRITETEXT takes three arguments: the table.column to be updated, the pointer that points to the data to be updated, and the data to be updated.

So to handle this from CF.
<cfstoredproc procedure="spInsertRow" datasource="#Application.dbConnection#">
<cfprocparam Type="IN" cfsqltype="CF_SQL_BLOB" value="#PreserveSingleQuotes(FORM.txtArea)#" dbvarname="@blobValue">
</cfstoredproc>

And with the SQL db create a stored procedure.
Create Procedure spInsertRow
@blobValue Text
As
DECLARE
@textptr binary(16)

BEGIN TRAN
SELECT @textptr=TEXTPTR(BlobFieldinTable) FROM Table (UPDLOCK)

WRITETEXT #table.blobfield @textptr @blobValue

COMMIT TRAN
GO

For retrieving the data,
DECLARE @txtptr binary(16), @blobLength

BEGIN TRAN
SELECT @txtptr=TEXTPTR(blobColumn),
@blobLength=DATALENGTH(blobColumn)
FROM Table (HOLDLOCK) WHERE ID=1

READTEXT table.blobColumn @txtptr 0 @blobLength
COMMIT TRAN

Another userful item to mention is that the LIKE clause doesn't work with TEXT. Instead you have to use the PATINDEX().

WHERE PATINDEX('%NAME%', blobColumn) <> 0

So I guess the overall assessment is that one can handle the blob functionality in the db. The UI just needs to be careful on how it handles the amount of memory a BLOB can consume.

Posted by Elyse at October 26, 2003 9:13 AM
Comments

That's a good point! I sure prefer to use nvarchar and limit it to 4000 chars, for performance and db "economy", but i see there are only two real solutions.
One is to limit my textarea validation to 3988 chars and the other to change the field type to ntext, something that i really don't see as a solution...
I DON'T want the users to type more than 4000 chars, because the database will become huge and slow to access. (and if i'm wrong i can't sort it, if i've change the field type to ntext...)

Anyway, i'm not sure what i'm going to do yet. I've even thinking of limited to 3.500 chars...
Thanx for the interest and congratulation for a fine work here.

Regards,
Dimitris Siskopoulos
(the user that post the message http://webforums.macromedia.com/coldfusion/messageview.cfm?catid=3&threadid=715619)

Posted by: Dimitris Siskopoulos at October 27, 2003 3:54 AM

I just wanted so say thank you guys ! i really like your site and i hope you'll continue to improving it

Posted by: Graz at May 3, 2004 8:59 AM

Hi, I wrote to many themes, but this is realy interresting.
Yes. I agree.
This is very interesting.
Thanks for the information!

Posted by: TTT at May 3, 2004 8:59 AM

Here's a little tidbit that I had to discover for myself and wasn't readily available on the net. When you return a CLOB from a stored procedure, it is sent is a Java array. If you were to just access the value without converting it, you get a reference to a java memory location for an object. It would look something like "[C@179565d". So you have to treat it like a standard ColdFusion array.

<cfstoredproc datasource="DSN" procedure="mypackage.myproc">
<cfprocparam cfsqltype="CF_SQL_CLOB" variable="variables.out_clob" type="out" maxlength="32000">
</cfstoredproc>

<cfoutput>#ArrayToList(variables.out_clob,"")#</cfoutput>

Posted by: Chris at June 10, 2005 11:59 AM

There is a further solution, which is to chain 4000 char varchar records, and break up and reassemble the larger blocks used at UI level.

Jerry

Posted by: Jerry Kew at February 20, 2006 3:46 AM