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 ;
Related
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
what i am tryin to do is make a table(#tbl) runtime and insert the data from the select statement from the database,as what i have done so far is
declare #tbl TABLE (
Item int
)
begin
insert into #tbl values select cid from tbl_custumer where cus_ph like '%'+'987'+'%'
select * from #tbl
end
as "select cid" statement returns multiple records
I think you might want the code to look like this:
begin
declare #tbl TABLE (
Item int
);
insert into #tbl(Item)
select cid
from tbl_custumer
where cus_ph like '%'+'987'+'%';
select *
from #tbl;
end;
Notes:
The begin/end block is not really necessary, but I'm guessing you want it for other reasons (a stored procedure, if, or something similar).
The values keyword is not needed when using insert . . . select.
Use semicolons at the end of each SQL statement. Although they are optional, they make the code easier to follow.
Question: Create a UDF that accepts the State Province and returns the associated Sales Tax Rate, StateProvinceCode and CountryRegionCode (Database is AdventureWorks2012)
Name took the place of State Province because there is no column
called 'State Province', and 'Name' contains the needed information.
This is what I did in the code below.
Is there another way to run this?
In this form Ambiguous column name keeps showing up.
CREATE FUNCTION fx_TxSpCr (#Name Nvarchar(50),
#TaxRate Smallmoney,
#StateProvinceCode Nchar(3),
#CountryRegionCode Nvarchar(3)
)
RETURNS TABLE
AS
RETURN (
SELECT Name,TaxRate,StateProvinceCode,CountryRegionCode
FROM Sales.SalesTaxRate s
JOIN Person.StateProvince t
ON s.StateProvinceID=t.StateProvinceID
JOIN Sales.SalesTerritory u
ON t.TerritoryID=u.TerritoryID
)
SELECT s.TaxRate,t.StateProvinceCode,u.CountryRegionCode
FROM fx_TxSpCr
GROUP BY Name
Thank you both for the contribution. This worked:
CREATE FUNCTION fx_TaxStCtry(#StateProvince nvarchar(50))
RETURNS #TaxStCtry TABLE
(TaxRate SmallMoney not null,
StateProvinceCode Nchar(3) not null ,
CountryRegionCode Nvarchar(3) not null)
AS
BEGIN INSERT #TaxStCtry
SELECT tr.TaxRat,sp.StateProvinceCode,sp.CountryRegionCode
FROM Person.StateProvince sp
JOIN Sales.SalesTaxRate tr
ON tr.stateprovinceid = sp.stateprovinceid
WHERE sp.Name=#StateProvince
RETURN
END
The ambiguity is coming from the lack of aliases in the select statement from your function. It seems like you are trying to use the aliases in the execution of the function, but they actually need to be contained within the function itself. (For example, all three tables have a "name" column.)
After correcting that issue you will find that you actually have not used any of the parameters you have set up for your function. Which does not have to be the full return set of the select statement contained within.
The correct path here is to start with a select statement that returns what you're needing and then turn that into a function. If the data is not being returned at a base level, then you're not ready to start creating a function.
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))
Scenario
I have a stored procedure written in T-Sql using SQL Server 2005.
"SEL_ValuesByAssetName"
It accepts a unique string "AssetName".
It returns a table of values.
Question
Instead of calling the stored procedure multiple times and having to make a database call everytime I do this, I want to create another stored procedure that accepts a list of all the "AssetNames", and calls the stored procedure "SEL_ValueByAssetName" for each assetname in the list, and then returns the ENTIRE TABLE OF VALUES.
Pseudo Code
foreach(value in #AllAssetsList)
{
#AssetName = value
SEL_ValueByAssetName(#AssetName)
UPDATE #TempTable
}
How would I go about doing this?
It will look quite crippled with using Stored Procedures. But can you use Table-Valued Functions instead?
In case of Table-Valued functions it would look something like:
SELECT al.Value AS AssetName, av.* FROM #AllAssetsList AS al
CROSS APPLY SEL_ValuesByAssetName(al.Value) AS av
Sample implementation:
First of all, we need to create a Table-Valued Parameter type:
CREATE TYPE [dbo].[tvpStringTable] AS TABLE(Value varchar(max) NOT NULL)
Then, we need a function to get a value of a specific asset:
CREATE FUNCTION [dbo].[tvfGetAssetValue]
(
#assetName varchar(max)
)
RETURNS TABLE
AS
RETURN
(
-- Add the SELECT statement with parameter references here
SELECT 0 AS AssetValue
UNION
SELECT 5 AS AssetValue
UNION
SELECT 7 AS AssetValue
)
Next, a function to return a list AssetName, AssetValue for assets list:
CREATE FUNCTION [dbo].[tvfGetAllAssets]
(
#assetsList tvpStringTable READONLY
)
RETURNS TABLE
AS
RETURN
(
-- Add the SELECT statement with parameter references here
SELECT al.Value AS AssetName, av.AssetValue FROM #assetsList al
CROSS APPLY tvfGetAssetValue(al.Value) AS av
)
Finally, we can test it:
DECLARE #names tvpStringTable
INSERT INTO #names VALUES ('name1'), ('name2'), ('name3')
SELECT * FROM [Test].[dbo].[tvfGetAllAssets] (#names)
In MSSQL 2000 I would make #allAssetsList a Varchar comma separated values list. (and keep in mind that maximum length is 8000)
I would create a temporary table in the memory, parse this string and insert into that table, then do a simple query with the condition where assetName in (select assetName from #tempTable)
I wrote about MSSQL 2000 because I am not sure whether MSSQL 2005 has some new data type like an array that can be passed as a literal to the SP.