I suspect you are simply not checking the length of the column accurately (like inspecting PRINT
or SELECT
output in Management Studio, which is truncated by the tool, not accurately reflecting what's actually in the database). There is no limitation on the number of characters that can be exposed or updated by a view, unless you introduce them, perhaps you are using an INSTEAD OF
trigger, or there is implicit conversion going on somewhere, or your data is being truncated before the update. Hard to tell without more details, which I hope you can furnish.
In the meantime, try this:
USE tempdb;
GO
CREATE TABLE dbo.foobar(x VARCHAR(MAX));
GO
CREATE VIEW dbo.v_foobar
WITH SCHEMABINDING
AS
SELECT x FROM dbo.foobar;
GO
INSERT dbo.v_foobar(x) VALUES('c');
GO
UPDATE dbo.v_foobar
SET x = REPLICATE(CONVERT(VARCHAR(MAX), 'c'), 8000)
+ REPLICATE(CONVERT(VARCHAR(MAX), 'c'), 8000);
GO
SELECT LEN(x), DATALENGTH(x)
FROM dbo.v_foobar;
GO
Results:
----- -----
16000 16000
I'm also not convinced that CHAR(34)
is the culprit.
UPDATE dbo.v_foobar
SET x = CHAR(34) + 'x'
+ REPLICATE(CONVERT(VARCHAR(MAX), 'c'), 800)
+ CHAR(34) + 'x'
+ REPLICATE(CONVERT(VARCHAR(MAX), 'c'), 800)
+ CHAR(34) + 'x'
+ REPLICATE(CONVERT(VARCHAR(MAX), 'c'), 800)
+ CHAR(34) + 'x'
+ REPLICATE(CONVERT(VARCHAR(MAX), 'c'), 800)
+ CHAR(34) + 'x'
+ REPLICATE(CONVERT(VARCHAR(MAX), 'c'), 800)
+ CHAR(34) + 'x'
+ REPLICATE(CONVERT(VARCHAR(MAX), 'c'), 800)
+ CHAR(34) + 'x'
+ REPLICATE(CONVERT(VARCHAR(MAX), 'c'), 800)
+ CHAR(34) + 'x'
+ REPLICATE(CONVERT(VARCHAR(MAX), 'c'), 800)
+ CHAR(34) + 'x'
+ REPLICATE(CONVERT(VARCHAR(MAX), 'c'), 800)
+ CHAR(34) + 'x'
+ REPLICATE(CONVERT(VARCHAR(MAX), 'c'), 800)
+ CHAR(34) + 'x'
+ REPLICATE(CHAR(34), 400)
+ 'x'
+ REPLICATE(CHAR(34), 400)
+ 'x'
+ REPLICATE(CHAR(34), 400)
+ 'x' + CHAR(34)
+ REPLICATE(CONVERT(VARCHAR(MAX), 'c'), 8000);
GO
SELECT LEN(x), DATALENGTH(x)
FROM dbo.v_foobar;
Results:
----- -----
17226 17226
I suspect that something else is happening to this string as it's being generated or before the command is passed to SQL Server.
PRINT @String;
will yield that it says PhoneNumber = 123-4567
(which treats it like an expression, 123
subtract 4567
, which equals -4444
), not PhoneNumber = '123-4567'
like in the example you hard-coded. So you should be escaping the values you're appending with two single-quotes:
SELECT @String = ' UPDATE ' + @Location +
' SET PhoneNumber = ''' + @PhoneNumber + '''
WHERE Room = ''' + @Room + ''';';
But better yet, to better protect yourself from SQL injection (see here, here, and here), you should have (a) check that @Location
is a valid table, (b) QUOTENAME()
it anyway, and (c) pass in the other two values as properly typed parameters rather than appending them to the string:
IF OBJECT_ID(N'dbo.' + @Location) IS NOT NULL
BEGIN
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'UPDATE dbo.' + QUOTENAME(@Location)
+ N' SET PhoneNumber = @PhoneNumber
WHERE Room = @Room;';
EXEC sys.sp_executesql @sql,
N'@PhoneNumber CHAR(8), @Room VARCHAR(10)',
@PhoneNumber, @Room;
END
And even better still, you shouldn't have a separate table for each Location
IMHO - Location should be a column. Then you wouldn't need dynamic SQL at all.
Best Answer
You can check the opposite (does not contain chars not in the 0-9 interval).
Be warned that telephone numbers typically contain also other characters (+,-,.). In that case, you can add allowed symbols to the list:
See
LIKE
(Transact-SQL) in the documentation.