Inserting "null" (literally) in to a stored procedure parameter - sql-server-2005

I'm trying to insert the word "Null" (literally) in to a parameter for a stored procedure. For some reason SqlServer seems to think I mean NULL and not "Null". If I do a check for
IF #LastName IS NULL // Test: Do stuff
Then it bypasses that because the parameter isn't null.
But when I do:
INSERT INTO Person (<params>) VALUES (<stuff here>, #LastName, <more stuff here>); // LastName is 'Null'
It bombs out saying that LastName doesn't accept nulls.
I would seriously hate to have this last name, but someone does... and it's bombing the application. We're using SubSonic 2.0 (yeah, it's fairly old but upgrading is painful) as our DAL and stepping through it, I see it does create the parameters properly (for what I can tell).
I've tried creating a temp table to see if I could replicate it manually but it seems to work just fine. Here is the example I create:
DECLARE #myval VARCHAR(50)
SET #myval = 'Null'
CREATE TABLE #mytable( name VARCHAR(50))
INSERT INTO #mytable VALUES (#myval)
SELECT * FROM #mytable
DROP table #mytable
Any thoughts on how I can fix this?
edit: The method the LastName is set is this -- myPerson.LastName = textBoxLastName.Text;
edit: Upon using SqlServer Profiler, I see that it IS sending null. Two things that's weird, I wonder why my "IF #lastName IS NULL" isn't firing off... but now I have to look at SubSonic further to see if something is changing last minute I wasn't aware of. I'll investigate this further and report back.
edit: The only constraint is a default value of ''.
edit: Ok, I've confirmed it IS SubSonic trying to play smart.
if (param.ParameterValue == null || Utility.IsMatch(param.ParameterValue.ToString(), "null"))
Good idea for using the Profiler, I entirely forgot about that.
final edit: It's worth noting, fur future reference, that SubSonic replaces this at the last minute in the data provider (in my case SqlDataProvider). In The DataService.cs where it calls Execute Scalar, the parameters have not been adjusted yet. They get adjusted when it runs the ExecuteScalar for the DataProvider, which is an abstract class (so Postgre and Oracle will each have their own bits of code). Specifically, the SubSonic.SqlDataProvider.AddParams is what bit me.

It's worth noting, fur future reference, that SubSonic replaces this at the last minute in the data provider (in my case SqlDataProvider). In The DataService.cs where it calls Execute Scalar, the parameters have not been adjusted yet. They get adjusted when it runs the ExecuteScalar for the DataProvider, which is an abstract class (so Postgre and Oracle will each have their own bits of code). Specifically, the SubSonic.SqlDataProvider.AddParams is what bit me.

Please try this:
Oops...I totally misunderstood the question. I think there should be some constraints set in the database column. Please try to write the insert query directly in DB and see if it bombs out.
I tried this and it bombs out as expected:
DECLARE #myval VARCHAR(50)
SET #myval = 'null'
CREATE TABLE #mytable( name VARCHAR(50) NULL CHECK (name <> 'NULL'))
INSERT INTO #mytable VALUES (#myval)
SELECT * FROM #mytable WHERE name is not null
DROP table #mytable
HTH

Related

Pass declare table variable to another stored procedure

I am sure the answer is NO, but I'll ask the expert anyway ;)
I've declared a table variable in my stored procedure.
DECLARE #OrderMapIds TABLE
(
OrderId INT NOT NULL,
NewOrderId INT NOT NULL
);
INSERT INTO #OrderMapIds (OrderId, NewOrderId)
SELECT [OrderId], [OrderId] FROM [tblOrder]
...
...
...
EXEC [AS.uspOrder_MoveOrder] #OrderMapIds = #OrderMapIds; --I need to move order ids based on the mapped id
I need to pass #OrderMapIds to [AS.uspOrder_MoveOrder]. The question is how?
CREATE PROCEDURE [AS.uspOrderItem_CopyRecord]
(
#OrderMapIds AS TABLE -- This thrown error
)
AS
BEGIN
...
...
...
END;
Now, I can accomplish this problem using Table-Valued Parameter (TVP). But if I could pass it without TVP, then it will be better (so I don't have to create TVP for small stuff).
Now, after looking at Google, I am sure the answer is NO (ie. I need to create TVP to accomplish task above). But I thought to ask the question in hope I might have missed something.
Any help is greatly appreciated.
Thanks
You are correct. The answer is indeed No.
In SQL Server, the only way to pass a table to a stored procedure is using a user defined table type.
You do have some confusion in the terms, though.
TVP is the parameter itself - so even if you could just pass any table variable a stored procedure - it would still be a Table Valued Parameter.
What you want to avoid (but can't) is a User Defined Table Type.
If this was allowed, you would end up with a stored procedure that takes in a table valued parameter with an unknown structure - And this could lead to errors, extremely cumbersome code, and worst of all - silently using the wrong data.
An interesting alternative, especially when the table structure is variable/dependent will be to convert data as JSON/XML ( data type for parameter will be NVARCHAR).
Way to go in your example will be
DECLARE #OrderMapIds NVARCHAR(MAX)=
(
SELECT [OrderId], [OrderId] FROM [tblOrder] FOR JSON PATH
);
...
...
...
EXEC [AS.uspOrder_MoveOrder] #OrderMapIds = #OrderMapIds;

DB2: How to get generated always as statement to work with session user

I need to get a userstamp into a table and have not managed to figure out how the GENERATED FOR EACH ROW ON UPDATE AS statement works with the SESSION_USER variable in DB2 10.5 (LUW).
Managed to get an implementation working using a function which has a fake variable for forcing the evaluation in update statements:
CREATE OR REPLACE FUNCTION XXX.CURRENT_USER( tmp varchar(128))
SPECIFIC xxx.XXX_CURRENT_USER
RETURNS VARCHAR(128)
CONTAINS SQL DETERMINISTIC NO EXTERNAL ACTION
BEGIN
RETURN session_user ;
END
GO
CREATE TABLE xxx (
i INTEGER,
t VARCHAR(128) GENERATED ALWAYS AS (XXX.CURRENT_USER(i))
)
However, would be nice have less "hacky" implementation for a basic thing like this.
For the time stamps there is that "FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP" statement but no equivalent for other register variables it seems.
Help is very much appreciated
Does this work?
CREATE TABLE xxx (
i INTEGER,
t VARCHAR(128) WITH DEFAULT session_user
);
I don't have DB2 on hand to check, but this is very similar to the syntax used in other databases (although the more typical syntax does not use WITH).

Insert statement with a NON-NULLABLE column

I have a SQL Server script that I'm using to insert some data into a database. I won't upload the whole script here just for space/time savings sake, but I will include the important bits.
So here is the problem. I have a table that has a column for some loginhtml, this column is of a non-nullable type. I would like for this column to be left blank on this particular add so it can default back to the parent that I'm pointing it at. So here we have the declaration for this important portion:
declare #loginTitle varchar(250), #loginHtml varchar(max)
And here we have what it will be set to:
set #loginHtml = null
And here is the insert part that is inevitably going to fail:
insert dbo.ApplicationLogin(ApplicationID, Title, Html)
select #appID, #loginTitle, #loginHtml
EDIT: How can I have this script "default" the loginhtml column to whatever the PARENT Application is? Is there some "IF" statement/clause that can be used to accomplish this?
As long as the column in non null, then you can't insert a null value into it. You could try setting it to a blank string or other default value. You could aslo select the parent's html and insert that instead. There is no way to skip over inserting any column.
As others have stated, if there is a Not Null constraint on the column, you are out of luck, but you could do
if #loginhtml is null
begin
set #loginhtml = ''
end
Or change
set #loginhtml = ''
to lookup whatever the default in the parent application is.
and you will write a blank instead of anything. You, obviously, run into whatever issues there will be with having no loginhtml, but if that's what you want that is what you want!
You can adjust your script:
insert dbo.ApplicationLogin(ApplicationID, Title, Html)
select #appID, #loginTitle, ISNULL(#loginHtml, '')
Or adjust your table and add a default constraint:
ALTER TABLE ApplicationLogin ADD DEFAULT (('')) FOR [Html];
I may not have mentioned this in the initial post, and I would like to apologize for that. But the way the database is set up, is applications can have parent applications, so setting the loginhtml to the parent application and "technically" skipping adding it to the new application can be done by doing this:
if(#loginHtml is not null)
begin
insert dbo.ApplicationLogin(ApplicationID, Title, Html)
select #appID, #loginTitle, #loginHtml
end
This runs successfully and makes the "#loginhtml" default to whatever the parent application has set for that value.

Update a variable number of parameters in a Stored Procedure

Assume the following please:
I have a table that has ~50 columns. I receive an import file that has information that needs to be updated in a variable number of these columns. Is there a method via a stored procedure where I can only update the columns that need to be updated and the rest retain their current value unchanged. Keep in mind I am not saying that the unaffected columns return to some default value but actually maintain the current value stored in them.
Thank you very much for any response on this.
Is COALESCE something that could be applied here as I have read in this thread: Updating a Table through a stored procedure with variable parameters
Or am I looking at a method more similar to what is being explained here:
SQL Server stored procedure with optional parameters updates wrong columns
For the record my sql skills are quite weak, I am just beginning to dive into this end of the pool
JD
Yes, you can use COALESCE to do this. Basically if the parameter is passed in as NULL then it will use the original value. Below is a general pattern that you can adapt.
DECLARE #LastName NVARCHAR(50) = 'John'
DECLARE #FirstName NVARCHAR(50) = NULL;
DECLARE #ID INT = 1;
UPDATE dbo.UpdateExample
SET LastName = COALESCE(#LastName, LastName), FirstName = COALESCE(#FirstName, FirstName),
WHERE ID = #ID
Also, have a read of this article, titled: The Impact of Non-Updating Updates
http://web.archive.org/web/20180406220621/http://sqlblog.com:80/blogs/paul_white/archive/2010/08/11/the_2D00_impact_2D00_of_2D00_update_2D00_statements_2D00_that_2D00_don_2D00_t_2D00_change_2D00_data.aspx
Basically,
"SQL Server contains a number of optimisations to avoid unnecessary logging or page flushing when processing an UPDATE operation that will not result in any change to the persistent database."

SQL Server 2008 stored procedure result as column default value

First of all, thank you guys. You always know how to direct me when I can't even find the words to explain what the heck I'm trying to do.
The default values of the columns on a couple of my tables need to be equal the result of some complicated calculations on other columns in other tables. My first thought is to simply have the column default value equal the result of a stored procedure. I would also have one or more of the parameters pulled from the columns in the calling table.
I don't know the syntax of how to do it though, and any time the word "stored" and "procedure" land next to each other in google I'm flooded with info on Parameter default values and nothing relating to what I actually want.
Half of that was more of a vent than a question...any ideas though? And plz plz don't say "Well, you could use an On-Insert Trigger to..."
You can't have the default be the result of a stored procedure, it has to be a function. If you can convert the procedure into a function, then you can use that function. If you cannot, then you must use a trigger.
You would have to convert that stored procedure to a user-defined function. There are different types of UDF's - the one you're looking at would be the scalar UDF - returning a single value.
So for instance you could create a function like this:
CREATE FUNCTION dbo.YourDefaultFunction(#Input1 INT, #Input2 VARCHAR(10))
RETURNS VARCHAR(100)
AS BEGIN
DECLARE #Result VARCHAR(100)
SET #Result = #Input2 + ' - giving: ' + CAST(#Input1 AS VARCHAR(5))
RETURN #Result
END
Of course, yours would be a lot more complicated :-)
Once you've done that, you can define this to be the default for a column of type VARCHAR(100) - either directly when declaring the table, or later on via an ALTER TABLE statement:
CREATE TABLE dbo.YourTable(.......
SomeColumn VARCHAR(100)
CONSTRAINT DF_YourTable_SomeColumn
DEFAULT (dbo.YourDefaultFunction(417, 'Test')),
.....)
or :
ALTER TABLE dbo.YourTable
ADD CONSTRAINT DF_YourTable_SomeColumn
DEFAULT (dbo.YourDefaultFunction(4711, 'Test2'))
FOR SomeColumn
Unfortunately, you cannot pass other columns as parameters to your function when defining it as a default value for a column.
Does that help??