Best way to select column where not in table - sql-server

I have a table with a unique column, "X".
I would like to pass a list to a stored procedure using a table value pair of X, and I would like back a list of all the X's that do not exist in the table.
What is the most efficient way to do this in SQL Server?
EDIT:
I've come up with this. Not sure how efficient it is:
CREATE TYPE StringList_TBLType AS TABLE (s NVARCHAR(255) NOT NULL PRIMARY KEY)
CREATE PROCEDURE [dbo].ReturnProductsNotExisting
(
#CatalogIdList StringList_TBLType READONLY
)
AS
BEGIN
SELECT s FROM #CatalogIdList
WHERE s NOT IN (SELECT CatalogId from Products)
END

Related

T-SQL OUTPUT clause to update a temp table

I have a utility script that is used to insert data into tables in my database. The script has a number of temp table in it that stores the new data to be inserted and a lot of it is related.
So, for example I have tables like so
DECLARE #Table1 TABLE
(
Table1ID INT
Table1Description VARCHAR(50)
Table1Code VARCHAR(5)
)
DECLARE #Table2 TABLE
(
Table2ID INT
Table2Description VARCHAR(50)
Table2Code VARCHAR(5)
)
DECLARE #Relationships TABLE
(
Table1Code VARCHAR(5)
Table2Code VARCHAR(5)
)
So the script populates the data in #Table1 and #Table2, but doesn't populate the ID fields. Once the data has been MERGEd into the database tables, I update the Table1ID and Table2ID fields in a separate statement as they are auto incrementing fields. Then when I use the #Relationships table to populate the database table, I can join to #Table1 and #Table2 to get the actual ID values.
I'm updating the script and I'm wondering if I can MERGE the data from #Table1/#Table2 into the database and update the ID fields in the temp table as part of the MERGE statement using the OUTPUT clause all in one statement?
I think the answer is no as I can't find anything mentioning updating an existing table with the OUTPUT clause, only inserting into a table.
I am still able to do what I need to do, so I'm not after alternatives. I just wondering if it is possible using the OUTPUT Clause
Thanks in advance

What does 'Unnecessary table scan' mean exactly

I have a table of names with Ids
Create table Names (
Id int,
Name nvarchar(500)
)
I'm trying to create a procedure that would select 1 name that matches the provided Id if Id is provided or select all names if no Id is provided
Create Procedure SelectNames
#Id int = null
AS
BEGIN
Select * From Names
Where IsNull(#Id, 0) = 0
Or Id = #Id
END
GO
But I get an error: 'Error: SR0015 : Microsoft.Rules.Data : Deterministic function call (ISNULL) might cause an unnecessary table scan.'
What does the 'unnecessary table scan' refer to in this instance?
And is there a better way to write the procedure?
The simplest way to remove the table scan is to create an index (probably unique) on your Id column. In general, one wouldn't expect a nullable Id value. With that index in place, finding a name by Id will not require scanning (or iterating through every row in) the table.
Regarding "better way to write the procedure" - once the nullability is removed, a simple SELECT without the WHERE should be fine.

how to calculate column to other table

i want to make column Customers_Balance on TBL_CUSTOMERS to show by defult the result of that stored procedures....
TBL_CUSTOMERS which it have the info of the customer, and it created as like that
CREATE TABLE TBL_CUSTOMERS
(
Customers_ID int PRIMARY KEY,
Customers_Name varchar(100) NOT NULL,
Customers_Phone varchar(100),
Customers_Address varchar(100),
Customers_Web varchar(100),
Customers_Balance decimal(16,0) not null,
);
TBL_CUSTOMERS_DETAILS which it have the details of all customer transactions , and it created as like that
CREATE TABLE TBL_CUSTOMERS_DETAILS
(
Customers_Details_ID int PRIMARY KEY,
Customers_ID int,
Customers_Details_Tybe varchar(50) not null,
Customers_Details_Date date not null,
Customers_Details_Amount decimal(16,0) not null,
);
i have created stored procedures to calculate the result of sum of customer's transactions balance and worked fine, and it created as like that
CREATE PROC SP_SUM_CUSTOMERS_DETAILS_AMOUNT
#ID INT
AS
SELECT SUM(Customers_Details_Amount)
FROM TBL_CUSTOMERS_DETAILS
Where Customers_ID = #ID
NOW
i want to make column Customers_Balance on TBL_CUSTOMERS to show by defult the result of that stored procedures....
how i can make something like that ??
Materializing values that can be calculated by other materialize values is usually a bad idea as it bears the risk of inconsistencies.
So you best drop the column Customers_Balance in TBL_CUSTOMERS and the procedure and then create a view which includes the customer's data and their balance. You can do so by a join and aggregation.
ALTER TABLE TBL_CUSTOMERS
DROP COLUMN Customers_Balance;
DROP PROCEDURE SP_SUM_CUSTOMERS_DETAILS_AMOUNT;
CREATE VIEW VW_CUSTOMERS
AS
SELECT C.Customers_ID,
C.Customers_Name,
C.Customers_Phone,
C.Customers_Address,
C.Customers_Web,
sum(CD.Customers_Details_Amount) Customers_Balance
FROM TBL_CUSTOMERS C
INNER JOIN TBL_CUSTOMERS_DETAILS CD
ON CD.Customers_ID = C.Customers_ID
GROUP BY C.Customers_ID,
C.Customers_Name,
C.Customers_Phone,
C.Customers_Address,
C.Customers_Web;
You are looking for a Computed Column
What you need to do is to create a scalar function rather than a stored procedure (simply change your current stored procedure into a scalar function), and then use this function in your computed column. This would give you an auto-updated results on your computed column.
So, redoing your work should be something like this :
-- CREATE THE SCALAR FUNCTION FIRST
CREATE FUNCTION SUM_CUSTOMERS_DETAILS_AMOUNT (#ID INT)
RETURNS INT
AS
BEGIN
RETURN (
SELECT SUM(Customers_Details_Amount)
FROM TBL_CUSTOMERS_DETAILS
WHERE Customers_ID = #ID
)
END
GO
-- NOW DROP THE CURRENT Customers_Balance COLUMN
ALTER TABLE TBL_CUSTOMERS
DROP COLUMN Customers_Balance
GO
-- CREATE THE COMPUTED COLUMN WITH THE FUNCTION
ALTER TABLE TBL_CUSTOMERS
ADD Customers_Balance AS dbo.SUM_CUSTOMERS_DETAILS_AMOUNT (Customers_ID)
GO

What is the best practice to insert multiple records to DB and get multiple records from DB in single instance using BizTalk?

I want to develop a BizTalk orchestration. Which should insert multiple records into multiple DB tables and retrieve inserted records from multiple DB tables, in single instance of orchestration. For this requirement, I'm able to insert the data in one instance, but seeing difficulty to retrieve the inserted data for that instance, as all the records has unique values for each record. For my situation, I should use stored procedures, to apply some other business logic. So I have 2 different methods by using "Wcf_Custom Adapter composite feature" by calling stored procedures, as stated below.
-> Method1
I have to develop a Stored procedure, which takes LoadDate("2016-05-12 10:11:22.147") as parameter along with inserting values and it will take care of inserting the records for that instance, by keeping the given LoadDate. Then immediately it will call Get stored procedure, which takes the LoadDate("2016-05-12 10:11:22.147") as parameter, then it will retrieve the recently inserted records from DB based on LoadDate value.
I know, Retrieving the data based on a date value from sql server is a bad practice and it will give performance issues too.
-> Method2
I'll design the inserting tables, with bool data type column name "New" and value will be 0 or 1. I'll develop a Insert Stored procedure, which inserts the data by giving the "New" column value as "1". Then immediately it will call Get stored procedure, which will not take no parameters, then it will retrieve the recently inserted records which are having "New" column indicator "1" from DB tables. Once it retrieves the data, then it will update "New" column value to "0".
I prefer this method2. But, do we have better option?
As #johns-305 mentioned in his comment. You shall use table value param in your sp. and assembly all your data in orchestration then make a call to this sp.
A sample sp may like below:
CREATE TYPE [dbo].[SampleDataTable_Type] AS TABLE(
[ID] [int] NOT NULL,
[Name] [varchar](50) NOT NULL,
PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (IGNORE_DUP_KEY = OFF)
)
GO
CREATE PROCEDURE [dbo].[sp_InsertSampleTableData]
(
#LoadDate DATETIME,
#data [SampleDataTable_Type] READONLY
)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO your_table(id, name,)
SELECT id, name FROM #data;
--Do whatever you want
SET NOCOUNT OFF
END
GO
I think your stored procedure may look like this:
create procedure myProc
#a int, #b varchar(100)
as
insert myTable(a,b,c)
OUTPUT inserted.* --this line
select a,b,c
from somewhere
where a=#a and b=#b

At a Format Constraint to A Create Table Statement

I am creating a table in SQL Server for one of my customers that is needing an Access DB converted to SQL Server. ON the tables Access has masked a column a certain way. They have a number lets say TP001111 and when I pull the value into SQL Server I get 1111. I have a table called VendorNumber and I need to format this number.
CREATE TABLE VendorNumber
(
V_ID NVARCHAR(8) NOT NULL PRIMARY KEY,
V_Name NVARCHAR(30) NOT NULL
)
I have tried researching how to do this and I can't find a good example. What is the best way to have this value formatted when it is inserted into the table. I need to have it inserted as TP001111. The current code I have to format the column is:
UPDATE VendorNumber
SET V_ID = 'TP' + RIGHT((REPLICATE('0',6) + TPPRM_ID),6)

Resources