sql calling custom function - tsql - sql

I am doing the following:
Insert into table1
(Phone#) values #Phone
There is a custom function which will format the phone number. It accepts as input parameter the phone number and returns the formatted version.
I tried the following but not sure it would not work:
Insert into table1
(Phone#) values fn_phone(#Phone)
It says fn_phone is not a recognized built in function name. Am I doing something wrong on how I am calling fn_phone?

Use two-part name when you are calling UDF
Try this:
Insert into table1
(Phone#) select dbo.fn_phone(#Phone)

try:
Insert into table1 (Phone#)
SELECT dbo.fn_phone(#Phone) (or whatever schema your function is in)

Assuming the function is from "dbo" schema :
Insert into table1
(Phone#) values (dbo.fn_phone(#Phone))

Related

Use a user defined function in an insert into

I have an scalar-valued function that takes a code of varchar(5) of one value and translates it to another value. I am attempting to use it in an INSERT INTO:
INSERT INTO AccountTable
(
[CustomerName],
[CurrencyAbbreviation]
)
SELECT
customers.CustomerAbbreviation,
funAMSGetCurrency(customers.Currency)
FROM CustomerTable customers
...but get an error saying funAMSGetCurrency is not a built in function. Is it possible to do a translation like this?
To call a user-defined function in SQL Server, you need to include the schema, which is probably dbo:
INSERT INTO AccountTable ([CustomerName], [CurrencyAbbreviation] )
SELECT customers.CustomerAbbreviation,
dbo.funAMSGetCurrency(customers.Currency)
FROM CustomerTable customers ;

How do I create a variable/parameter that is a string of values in SQL SSMS that I can use as a substitute in my where clause?

This may be a very basic question, but I have been struggling with this.
I have a SSMS query that I'll be using multiple times for a large set of client Ids. Its quite cumbersome to have to amend the parameters in all the where clauses every time I want to run it.
For simplicity, I want to convert a query like the one below:
SELECT
ID,
Description
From TestDb
Where ID in ('1-234908','1-345678','1-12345')
to a query of the format below so that I only need to change my variable field once and it can be applied across my query:
USE TestDb
DECLARE #ixns NVARCHAR(100)
SET #ixns = '''1-234908'',''1-345678'',''1-12345'''
SELECT
ID,
Description
From TestDb
Where ID IN #ixns
However, the above format doesn't work. Can anyone help me on how I can use a varchar/string variable in my "where" clause for my query so that I can query multiple IDs at the same time and only have to adjust/set my variable once?
Thanks in advance :D
The most appropriate solution would be to use a table variable:
DECLARE #ixns TABLE (id NVARCHAR(100));
INSERT INTO #ixns(id) VALUES
('1-234908'),
('1-345678'),
('1-12345');
SELECT ID, Description
FROM TestDb
WHERE ID IN (SELECT id FROM #ixns);
You can load ids to temp table use that in where condition
USE TestDb
DECLARE #tmpIDs TABLE
(
id VARCHAR(50)
)
insert into #tmpIDs values ('1-234908')
insert into #tmpIDs values ('1-345678')
insert into #tmpIDs values ('1-12345')
SELECT
ID,
Description
From TestDb
Where ID IN (select id from #tmpIDs)
The most appropriate way is to create a table type because it is possible to pass this type as parameters.
1) Creating the table type with the ID column.
create type MyListID as table
(
Id int not null
)
go
2) Creating the procedure that receives this type as a parameter.
create procedure MyProcedure
(
#MyListID as MyListID readonly
)
as
select
column1,
column2
...
from
MyTable
where
Id in (select Id from #MyListID)
3) In this example you can see how to fill this type through your application ..: https://stackoverflow.com/a/25871046/8286724

Insert empty string into INT column for SQL Server

A SAMPLE table has only one column ID of type int, default null.
In Oracle when I do:
insert into SAMPLE (ID) values ('');
the new record is added with blank value. But in SQL Server 2008, when I run the same insert statement, the new record has the value of 0.
Is there a way to force SQL Server 2008 to default blank string to NULL instead of 0 (for numerical type of columns)?
Assuming that your INSERT statement is part of a stored procedure re-used in many places of your application (or, perhaps, is a batch always constructed by the same part of the client code) and that the inserted value is a number passed as a string argument, you could modify the INSERT like this:
INSERT INTO SAMPLE (ID) VALUES (NULLIF(#argument, ''));
Use NULL instead.
insert into SAMPLE (ID) values (NULL);
How about another idea - define an INSTEAD OF INSERT Trigger.
Despite the fact that you're trying to insert a string, with this the operation is "intercepted", empty string is replaced by NULL, and the insert succeeds.
If you define this trigger on your table, then you can continue to insert empty string as before, with no other changes.
Edit: As Martin Smith points out, this effectively is a comparison to 0 (the equivalent of empty string as an int) meaning you won't be able to store 0 in this table. I leave this answer here in case that's acceptable to your situation - either that or re-do all your queries!
CREATE TRIGGER EmptyStringTrigger
ON [SAMPLE]
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO [SAMPLE](ID)
SELECT CASE
WHEN ID = '' THEN NULL
ELSE ID
END
FROM inserted
END
SQL Fiddle example
You can't insert a 'string' into a int column. Oracle must be just handling that for you.
Just try inserting NULL if that's what you need.
insert into SAMPLE (ID) values (NULL);
One more option
insert into SAMPLE (ID) values (DEFAULT)

Calling Scalar-valued Functions in SQL

I have migrated a database from oracle, and now have a few Scalar-valued Functions.
However, when I call them, I get an error saying:
Cannot find either column "dbo" or the user-defined function or aggregate "dbo.chk_mgr", or the name is ambiguous.
I'm calling it like this:
SELECT dbo.chk_mgr('asdf')
What am I doing wrong?
Are you sure it's not a Table-Valued Function?
The reason I ask:
CREATE FUNCTION dbo.chk_mgr(#mgr VARCHAR(50))
RETURNS #mgr_table TABLE (mgr_name VARCHAR(50))
AS
BEGIN
INSERT #mgr_table (mgr_name) VALUES ('pointy haired boss')
RETURN
END
GO
SELECT dbo.chk_mgr('asdf')
GO
Result:
Msg 4121, Level 16, State 1, Line 1
Cannot find either column "dbo" or the user-defined function
or aggregate "dbo.chk_mgr", or the name is ambiguous.
However...
SELECT * FROM dbo.chk_mgr('asdf')
mgr_name
------------------
pointy haired boss
Can do the following
PRINT dbo.[FunctionName] ( [Parameter/Argument] )
E.g.:
PRINT dbo.StringSplit('77,54')
That syntax works fine for me:
CREATE FUNCTION dbo.test_func
(#in varchar(20))
RETURNS INT
AS
BEGIN
RETURN 1
END
GO
SELECT dbo.test_func('blah')
Are you sure that the function exists as a function and under the dbo schema?
You are using an inline table value function. Therefore you must use Select * From function.
If you want to use select function() you must use a scalar function.
https://msdn.microsoft.com/fr-fr/library/ms186755%28v=sql.120%29.aspx
Make sure you have the correct database selected. You may have the master database selected if you are trying to run it in a new query window.

How do I return a new IDENTITY column value from an SQLServer SELECT statement?

I'm inserting into an SQLServer table with an autoincrementing key field. (I believe this is called an IDENTITY column in SQLServer.)
In Oracle, I can use the RETURNING keyword to give my INSERT statement a results set like a SELECT query that will return the generated value:
INSERT INTO table
(foreign_key1, value)
VALUES
(9, 'text')
RETURNING key_field INTO :var;
How do I accomplish this in SQLServer?
Bonus: Okay, nice answers so far, but how do I put it into a single statement, if possible? :)
In general, it can't be done in a single statement.
But the SELECT SCOPE_IDENTITY() can (and should) be placed directly after the INSERT statement, so it's all done in the same database call.
Example:
mydb.ExecuteSql("INSERT INTO table(foreign_key1, value) VALUES(9, 'text'); SELECT SCOPE_IDENTITY();");
You can use OUTPUT, but it has some limitations you should be aware of:
http://msdn.microsoft.com/en-us/library/ms177564.aspx
SELECT SCOPE_IDENTITY()
Edit: Having a play...
If only the OUTPUT clause supported local variables.
Anyway, to get a range of IDs rather than a singleton
DECLARE #Mytable TABLE (keycol int IDENTITY (1, 1), valuecol varchar(50))
INSERT #Mytable (valuecol)
OUTPUT Inserted.keycol
SELECT 'harry'
UNION ALL
SELECT 'dick'
UNION ALL
SELECT 'tom'
Edit 2: In one call. I've never had occasion to use this construct.
DECLARE #Mytable TABLE (keycol int IDENTITY (1, 1), valuecol varchar(50))
INSERT #Mytable (valuecol)
OUTPUT Inserted.keycol
VALUES('foobar')
In addition to ##IDENTITY, you should also look into SCOPE_IDENTITY() and IDENT_CURRENT(). You most likely want SCOPE_IDENTITY(). ##IDENTITY has a problem in that it might return an identity value created in a trigger on the actual table that you're trying to track.
Also, these are single-value functions. I don't know how the Oracle RETURNING keyword works.
SCOPE_IDENTITY
It depends on your calling context.
If you're calling this from client code, you can use OUTPUT and then read the value returned.
DECLARE #t TABLE (ColID int IDENTITY, ColStr varchar(20))
INSERT INTO #t (ColStr)
OUTPUT Inserted.ColID
VALUES ('Hello World')
Result:
ColID
-----------
1
If you're wrapping this in a stored procedure, using OUTPUT is more work. There, you'll want to use SCOPE_IDENTITY(), but you can't do it in a single statement. Sure, you can put multiple statements on a single line with a ';' separator, but that's not a single statement.
DECLARE #idValue int
DECLARE #t TABLE (ColID int IDENTITY, ColStr varchar(20))
INSERT INTO #t (ColStr) VALUES ('Hello World')
SELECT #idValue = SCOPE_IDENTITY()
Result: #idValue variable contains identity value. Use an OUTPUT parameter to return the value.
You can use OUTPUT INTO, which has the additional benefits of being able to capture multiple identities inserted.
INSERT INTO table(foreign_key1, value)VALUES(9, 'text');SELECT ##IDENTITY;