Truncate SQL varchar column - sql

I currently have a column of varchar(3000). I want to reduce that to 400 characters.
When I execute this query:
ALTER TABLE [dbo].[App]
ALTER COLUMN SpecialInstructions VARCHAR(400) NOT NULL
I get this error:
Msg 8152, Level 16, State 14, Line 1
String or binary data would be truncated.
How do I set where previous data in that column would just be cut off? I'm using a development database, so it wouldn't matter if I was losing information. Or is there a better way to do this? Thanks in advance.

update [dbo].[App]
set SpecialInstructions = left(SpecialInstructions, 400)
You can optionally add a WHERE clause to make sure only too long values are shortened:
where len(SpecialInstructions) > 400
This is to reduce the number of rows updated. Keeps transaction smaller, incl write-sets.

Related

Cannot add NOT NULL constraint [duplicate]

So I want to change a column in my SQL Server database to not allow nulls, but I keep getting an error. this is the sql statement I am using:
alter table [dbo].[mydatabase] alter column WeekInt int not null
and this is the error I am getting :
Msg 515, Level 16, State 2, Line 1
Cannot insert the value NULL into column 'WeekInt', table 'CustomerRadar.dbo.tblRWCampaignMessages'; column does not allow nulls. UPDATE fails.
The statement has been terminated.
I'm pretty sure my sql is right, and there are no nulls currently in the column I am trying to change so I am really not sure as to what is causing the problem. Any ideas? I'm stumped.
Clearly, the table has NULL values in it. Which you can check with:
select *
from mydatabase
where WeekInt is NULL;
Then, you can do one of two things. Either change the values:
update mydatabase
set WeekInt = -1
where WeekInt is null;
Or delete the offending rows:
delete from mydatabase
where WeekInt is null;
Then, when all the values are okay, you can do the alter table statement.
If you are trying to change a column to not null, and you are getting this error message, yet it appears the column has no nulls, ensure you are checking for is null and not = null (which gives different results).
Select * from ... where column is null
instead of
Select * from ... where column = null
I am adding this because it tripped me up and took a while to resolve.
This will work. You should send a default value, then it will change all the previous record to -1 in this example.
alter table [dbo].[mydatabase] alter column WeekInt int not null DEFAULT '-1';

Early execution of "sp_rename" causes query to fail

I'm having a strange problem with an MSSQL Query that I'm trying to run in Microsoft SQL Server 2014. It is an update script for my database structure. It should basically rename a Column (from Price to SellingPrice) of a Table after its content was merged to another one.
USE db_meta
GO
DECLARE #BakItemPrices TABLE
(
ItemNum int,
Price int,
CashPrice int
)
-- backup old prices
insert into #BakItemPrices
select ItemNum, Price from dbo.ItemInfo
-- merge into other table
alter table ShopInfo
add column Price int NOT NULL DEFAULT ((0))
update ShopInfo
set ShopInfo.Price = i.Price
from ShopInfo s
inner join #BakItemPrices i
on s.ItemNum = i.ItemNum
GO
-- rename the column
exec sp_rename 'ItemInfo.Price', 'SellingPrice', 'COLUMN' -- The Debugger executes this first
GO
This query always gave me the error
Msg 207, Level 16, State 1, Line 13
Invalid column name 'Price'.
I couldn't understand this error until I debugged the query. I was amazed as I saw that the debugger wont even hit the breakpoint I placed at the backup code and says that "its unreachable because another batch is being executed at the moment".
Looking further down I saw that the debugger instantly starts with the exec sp_rename ... line before it executes the query code that I wrote above. So at the point my backup code is being executed the Column is named SellingPrice and not Price which obviously causes it to fail.
I thought queries get processed from top to bottom? Why is the execute sequence being executed before the code that I wrote above?
Script is sequenced from top to down. But some changes to schema is "visible" after the transaction with script is committed. Split your script into two scripts, it can help.

Msg 8152, Level 16, State 14, Line XXX String or binary data would be truncate

Scenario: A large stored procedure is run thousands of time a day, 6 days a weeks every year. For this one specific situation I'm getting an error
Msg 8152, Level 16, State 14, Line 114
String or binary data would be truncated
This stored procedure is about 800 lines of code, with lots of parameters, lots of variables and lots of tables.
Go
#exampleParam varchar(30)
#exampleParam datetime
DECLARE #declaredvara VARCHAR(50);
DECLARE #declaredvarb VARCHAR(50); -- where the line error is according to the printout
DECLARE #declaredvarc VARCHAR(50);
DECLARE #declaredvard VARCHAR(50); -- where line error is adjusted for comments in front of GO
BEGIN TRANS
-- some calculations (700+ lines)
COMMIT TRANS
--error catch
ROLLBACK TRANS
Problem: I'm want to know if its possible to get an accurate Line error read, so I can at least narrow down which tables I have to check. There are tons of tables involved in this stored procedure.
*** Both declared variables(before and after adjustment of GO) it points to are dead weight, they're nvr used.
Bonus info: I ran the stored procedure with params populated and params = '' except for the datetimes. In both cases I got the same error. However, I know the stored procedure works because it's being used thousands of times a day w/out this error.
EXEC SP '','','','','2014-11-6'
EXEC SP 'XX_XX_XX','',1,'','2014-11-6'
--both return the same error of Msg 8152, Level 16, State 14
--XX is a specific serialnum.
--However all other serialnum have no problem
EDIT: The DB is running SQL Server 2005
EDIT2: I'm using SQL Server 2008 to edit. - So debug isn't an option
Used that it will fix Msg 8152, Level 16, State 14, Line 114
String or binary data would be truncated.
SET ansi_warnings OFF
GO
BEGIN CATCH
DECLARE #body VARCHAR(4000)
SET #body='<b>Exception in spname </b><br/>'
SET #body=#body + ( SELECT
'<b>Error No :</b> '+ CONVERT(VARCHAR(100),ERROR_NUMBER()) +'<br/>'
+'<b>Error Severity :</b> '+CONVERT(VARCHAR(1000),ERROR_SEVERITY()) +'<br/>'
+'<b>Error State :</b> '+CONVERT(VARCHAR(1000),ERROR_STATE()) + '<br/>'
+'<b>Error Procedure :</b> '+CONVERT(VARCHAR(1000),ERROR_PROCEDURE())+'<br/>'
+'<b>Error Line :</b> '+CONVERT(VARCHAR(100),ERROR_LINE())+'<br/>'
+'<b>Error Message :</b> '+CONVERT(VARCHAR(2000),ERROR_MESSAGE()));
END CATCH
This error indicates that you are going to store some thing bigger that it's storage. you may need to check if you are going to store some string with more that 50 characters in #declaredvara or #declaredvarb or #declaredvarc or #declaredvard or any other variables or table columns. for example you may define #test as varchar(2) and then try to insert 'vahid' into it. in this case similar exception will be thrown. There is 2 way(as I know) that you can find the error ocurance line:
If you need to find the exact line of error occurrence you may need to debug you SP using sql server debug tools(Read more about debugging in Sql Server here)
You can also use TRY...CATCH blocks to check which block of code in you SP causes the error.
It turns out one of the variables in the area was declared but never given a value.
That variable was later used as a param in executing another stored procedure from within.
Which resulted in a null param being passed into a param that couldn't contain it.
Thanks everyone for the responses.
if your inserting in varchar(3) and selecting from varchar(10), you are getting the error. You have to design them same as varchar(3) or varchar(10).

SQL Column will not allow entry after being altered

I have a SQL table that has a column "Stamp" the was originally setup as nchar(10). The data that was entered in this field was only 9 characters long (ie. XX111.jpg) However, I have changed the format of the data being entered. It is now XX-XXX111.jpg. I ran this alter statement to increase the column size:
Alter Table tblData
Alter Column Stamp nvarchar(50)
Afterwards I would run an update statement to update the NULL values in the database:
Update tblData Set Stamp = 'XX-XXX111.jpg' where Updated > '2014-08-01' and Stamp is null
When I do this I get the following error:
(22 row(s) affected)
Msg 8152, Level 16, State 13, Procedure ChangedMECTrigger, Line 31
String or binary data would be truncated.
The statement has been terminated.
I don't understand how this is not working. Where am I going wrong?
You apparently have a trigger on the table:
ChangedMECTrigger
You need to update the data length on this too.
You can find those in SSMS here:
there's a trigger tied to tblData called ChangedMECTrigger. Something in the trigger's logic is causing the error. You could temporarily disable the trigger prior to running your update tblData... statement like this:
disable trigger ChangedMECTrigger on tblData
Update tblData Set Stamp = 'XX-XXX111.jpg' where Updated > '2014-08-01' and Stamp is null
enable trigger ChangedMECTrigger on tblData
or you could look at the trigger's code to find the issue. Chances are there's something in the trigger using nchar(10) still and needs to be updated to nvarchar(50).

alter table then update in single statement

I have a requirement where I need to Alter (Add 2 columns) and then update the same table.
Here is the query I tried:
ALTER TABLE A
ADD c1 int,c2 varchar(10)
UPDATE A set c1 = 23, c2 = 'ZZXX'
I need to run the above two queries at a time.
I am using Talend ETL tool, in this we have a component tMssqlrow, which allow us to run multiple queries (I am using 10 to 15 update queries in single component).
But the above query is not working.
I tested in DataBase Microsoft SQL. i am getting the below error :
Msg 207, Level 16, State 1, Line 5
Invalid column name 'c1'. Msg 207,
Level 16, State 1, Line 5
Invalid column name 'c2'.
can any one help me resolve this problem.
You can't do this exactly in a single statement (or batch) and it seems the tool you are using does not support GO as a batch delimiter.
You can use EXEC to run it in a child batch though.
ALTER TABLE A
ADD c1 INT, c2 VARCHAR(10);
EXEC('
UPDATE A
SET c1 = 23,
c2 = ''ZZXX'';
');
NB: All single quotes in the query need to be doubled up as above to escape them inside a string literal.
Or alternatively you could achieve similar results in a single statement with the aid of some default constraints.
ALTER TABLE A
ADD c1 INT NULL CONSTRAINT DF_A_c1 DEFAULT 23 WITH VALUES,
c2 VARCHAR(10) CONSTRAINT DF_A_c2 NULL DEFAULT 'ZZXX' WITH VALUES;
But this is not exactly the same as the original query as the default constraints will be left behind and may need to be dropped.
Use GO between your 2 queries.
Try this
ALTER TABLE A ADD c1 int,c2 varchar(10)
GO
UPDATE A set c1 = 23, c2 = 'ZZXX'
GO