sql temp table and while? - sql

I have a table (for example) with products and second with descriptions of these products.
I've created in procedure with one temp table which contains all ID of products that are NOT in table with description. Now I want to add these all descriptions for Ids from temp table. How can I achieve this? Loop cant be I think cause it will never end.
Please help ;)
I cannot use a trigger, and I'm using SQL Server 2016.
IF OBJECT_ID('tempdb.dbo.#Pr') IS NOT NULL
DROP TABLE #Pr;
CREATE TABLE #Pr
(
[Id] int
);
INSERT INTO #Pr
SELECT
[Id]
FROM
[db].[Products]
IF OBJECT_ID('tempdb.dbo.#Pr2') IS NOT NULL
DROP TABLE #Pr2;
CREATE TABLE #Pr2
(
[Id] int
);
INSERT INTO #Pr2
SELECT
[Id]
FROM
#Pr p1
WHERE
NOT EXISTS (SELECT [Id]
FROM [db].[Descriptions] p2
WHERE p1.[Id] = p2.[Id])
IF EXISTS (SELECT NULL FROM #Pr2)

You seem to want insert with a check that something is not already in the table. NOT EXISTS can be used for this purpose:
insert into products (product, description)
select product, description
from temp_products tp
where not exists (select 1 from products p where p.product = tp.product);

Related

SQL Server: update rows that take part in grouping

I'm using SQL Server 2017 (v14.0).
I have two tables with one-to-many relationship. I need to group the rows in the "Orders" table and by this info create the row in the "Transactions" table, then I need set the relationship - for a created transaction I need set the TransactionId to related order's rows in one query/transaction flow to keep the consistency.
I correctly insert the new row by grouped data, but can't update the related rows in "Orders" table to set the relationship (TransactionId) for related "Transactions".
Can you, please, help with composing the query statement or get the clue to move in the right direction?
CREATE TABLE [dbo].[Orders]
(
[OrderId] INT NOT NULL,
[TransactionId] INT NULL,
[OrderVolume] DECIMAL(18, 8) NOT NULL,
[OrderCurrencyId] INT NOT NULL,
)
CREATE TABLE [dbo].[Transactions]
(
[TransactionId] INT NULL,
[Volume] DECIMAL(18, 8) NOT NULL,
)
INSERT INTO Transactions (Volume)
OUTPUT INSERTED.[TransactionId] --also need to update the rows in "Orders" that take a part in grouping to set the relationship
SELECT
SUM(OrderVolume) AS OrderVolume,
FROM Orders
GROUP BY Orders.OrderCurrencyId
The problem with the OUTPUT clause in an INSERT statement is that it doesn't allow you to select any field from the source table.
You can achieve this using MERGE statement instead:
DECLARE #t TABLE([TransactionId] INT, [OrderCurrencyId] INT)
MERGE Transactions trgt
USING
(
SELECT
SUM(OrderVolume) AS OrderVolume
, Orders.OrderCurrencyId AS OrderCurrencyId
FROM
Orders
GROUP BY
Orders.OrderCurrencyId
) AS src ON (1=0)
WHEN NOT MATCHED THEN
INSERT ( [Volume] ) VALUES (src.OrderVolume)
OUTPUT [inserted].[TransactionId], src.[OrderCurrencyId]
INTO #t;
UPDATE Orders
SET TransactionId = t.TransactionId
FROM Orders
JOIN #t t ON Orders.OrderCurrencyId = t.OrderCurrencyId
Demo here

How to split data in SQL Server table row

I have table of transaction which contains a column transactionId that has values like |H000021|B1|.
I need to make a join with table Category which has a column CategoryID with values like H000021.
I cannot apply join unless data is same.
So I want to split or remove the unnecessary data contained in TransctionId so that I can join both tables.
Kindly help me with the solutions.
Create a computed column with the code only.
Initial scenario:
create table Transactions
(
transactionId varchar(12) primary key,
whatever varchar(100)
)
create table Category
(
transactionId varchar(7) primary key,
name varchar(100)
)
insert into Transactions
select'|H000021|B1|', 'Anything'
insert into Category
select 'H000021', 'A category'
Add computed column:
alter table Transactions add transactionId_code as substring(transactionid, 2, 7) persisted
Join using the new computed column:
select *
from Transactions t
inner join Category c on t.transactionId_code = c.transactionId
Get a straighforward query plan:
You should fix your data so the columns are the same. But sometimes we are stuck with other people's bad design decisions. In particular, the transaction data should contain a column for the category -- even if the category is part of the id.
In any case:
select . . .
from transaction t join
category c
on transactionid like '|' + categoryid + |%';
Or if the category id is always 7 characters:
select . . .
from transaction t join
category c
on categoryid = substring(transactionid, 2, 7)
You can do this using query :
CREATE TABLE #MyTable
(PrimaryKey int PRIMARY KEY,
KeyTransacFull varchar(50)
);
GO
CREATE TABLE #MyTransaction
(PrimaryKey int PRIMARY KEY,
KeyTransac varchar(50)
);
GO
INSERT INTO #MyTable
SELECT 1, '|H000021|B1|'
INSERT INTO #MyTable
SELECT 2, '|H000021|B1|'
INSERT INTO #MyTransaction
SELECT 1, 'H000021'
SELECT * FROM #MyTable
SELECT * FROM #MyTransaction
SELECT *
FROM #MyTable
JOIN #MyTransaction ON KeyTransacFull LIKE '|'+KeyTransac+'|%'
DROP TABLE #MyTable
DROP TABLE #MyTransaction

Inserting multiple rows in temp table without loop

This question has already been asked several times but the solution is not working for me. I don't know why.
Actually i am trying to create a temp table in sql query where i am inserting some records in temp table using select into but everytime it returns empty row:
here is what i am trying:
Create Table #TempTable
(
EntityID BIGINT
)
INSERT INTO #TempTable (EntityID)
SELECT pkEntityID FROM Employee WHERE EmpID = 45
Select * from #TempTable
Corresponding to 45 , there are 10 rows in Employee table. IS it like I have to do something else or a loop like structure here as we can only insert one row in a table at once?
This has been stated in the comments, all of which i up-voted, but to answer your question... there isn't anything else you have to do. There clearly isn't an EmpID = 45 in your source table. Here's a reproducible example:
Declare #Employee Table (pkEntityID bigint, EmpID int)
insert into #Employee (pkEntityID, EmpID)
values
(32168123,45),
(89746541,45),
(55566331,45),
(45649224,12)
Create Table #TempTable
(
EntityID BIGINT
)
INSERT INTO #TempTable (EntityID)
SELECT pkEntityID FROM #Employee WHERE EmpID = 45
Select * from #TempTable
drop table #TempTable
Have you accidentally also created the Employee table in the master database and you are currently connected to the master database?

Is it possible to create indexes on a temp table when using SELECT INTO?

I am loading data from a CSV file into a temp staging table and this temp table is being queried a lot. I looked at my execution plan and saw that a lot of the time is spent scanning the temp table.
Is there any way to create index on this table when I SELECT INTO it?
SELECT *
FROM TradeTable.staging.Security s
WHERE (
s.Identifier IS NOT NULL
OR s.ConstituentTicker IS NOT NULL
OR s.CompositeTicker IS NOT NULL
OR s.CUSIP IS NOT NULL
OR s.ISIN IS NOT NULL
OR s.SEDOL IS NOT NULL
OR s.eSignalTicker IS NOT NULL)
The table created by SELECT INTO is always a heap. If you want a PK/Identity column you can either do as you suggest in the comments
CREATE TABLE #T
(
Id INT IDENTITY(1,1) PRIMARY KEY,
/*Other Columns*/
)
INSERT INTO #T
SELECT *
FROM TradeTable.staging.Security
Or avoid the explicit CREATE and need to list all columns out with
SELECT TOP (0) IDENTITY(int,1,1) As Id, *
INTO #T
FROM TradeTable.staging.Security
ALTER TABLE #T ADD PRIMARY KEY(Id)
INSERT INTO #T
SELECT *
FROM TradeTable.staging.Security

How to prevent an entry in one table from existing in another table

I have 3 tables in SQL Server 2008
Clubs with a PK of ID and a Name.
Products which has a PK of ID, a FK of ClubID , a Name, a ShortCode and a Keyword.
There is a UK to enforce that there are no duplicate keywords for combinations of ShortCode/Keyword.
ProductAdditionalShortCodes. This has a PK of ID, a FK of ProductID and a Keyword
The idea is to prevent any shortcode/keyword combination of products to point to different clubs and also to prevent the creation of duplicate short/code keyword combinations
I have a solution that works, but feels clunky, and could under certain circumstances fail if multiple users happened to update multiple entries at the same time. (Hypothetically)
How can I add some form of constraint to the DB to prevent the Keyword in the Main table from being the same as in the Additional table and the other way round?
Following is a sample script to create the scenario and some of the examples I want to prevent. I am not opposed to changing the DB design if the impact of the change would not disrupt too many other aspects of the solution. (I realize this is subjective)
use Tinker
if exists (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.ProductAdditionalKeywords') AND type in (N'U'))
drop table dbo.ProductAdditionalKeywords
go
if exists (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.Products') AND type in (N'U'))
drop table dbo.Products
go
if exists (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.Clubs') AND type in (N'U'))
drop table dbo.Clubs
go
create table dbo.Clubs (
ID int not null identity(1,1)
,Name varchar(50) not null
,constraint PK_Clubs primary key clustered ( ID )
)
go
alter table dbo.Clubs add constraint UK_Clubs__Name unique ( Name )
go
create table dbo.Products (
ID int not null identity(1,1)
,ClubID int not null
,Name varchar(50) not null
,ShortCode varchar(50) not null
,Keyword varchar(50) not null
,constraint PK_Products primary key clustered ( ID )
)
go
alter table dbo.Products add constraint UK_Products__ShortCode_Keyword unique ( ShortCode , Keyword )
go
alter table dbo.Products add constraint UK_Products__Name unique ( Name )
go
alter table dbo.Products add constraint FK_Products_ClubID foreign key ( ClubID ) references dbo.Clubs ( ID )
go
create table dbo.ProductAdditionalKeywords (
ID int not null identity(1,1)
,ProductID int not null
,Keyword varchar(50) not null
,constraint PK_ProductAdditionalKeywords primary key clustered ( ID )
)
go
alter table dbo.ProductAdditionalKeywords add constraint FK_ProductAdditionalKeywords_ProductID foreign key ( ProductID ) references dbo.Products ( ID )
go
alter table dbo.ProductAdditionalKeywords add constraint UK_ProductAdditionalKeywords__Keyword unique ( Keyword )
go
insert into dbo.Clubs ( Name )
select 'Club 1'
union all select 'Club 2'
insert into dbo.Products (ClubID,Name,Shortcode,Keyword)
select 1,'Product 1','001','P1'
union all select 1,'Product 2','001','P2'
union all select 1,'Product 3','001','P3'
union all select 2,'Product 4','002','P4'
union all select 2,'Product 5','002','P5'
union all select 2,'Product 6','002','P6'
insert into dbo.ProductAdditionalKeywords (ProductID,Keyword)
select 1,'P1A'
union all select 1,'P1B'
union all select 2,'P2A'
union all select 2,'P2B'
/*
What can be done to prevent the following statements from beeing allowed based on the reason in the comments?
*/
--insert into dbo.ProductAdditionalKeywords (ProductID,Keyword) values ( 1 , 'P2' ) -- Main keyword for product 2
--update dbo.Products set Keyword = 'P1A' where ID = 2 -- Additional keyword for product 1
--insert into dbo.ProductAdditionalKeywords (ProductID,Keyword) values ( 3 , 'P1' ) -- Main ShortCode/Keyword combination for product 1
/*
At the moment I look at the following view to see if the proposed(new/updated) Keyword/Shortcode combination already exists
If it already exists I pevent the insert/update
Is there any way to do it in the DB via constraints rather than in the BLL?
*/
select ShortCode,Keyword,count([ClubID]) as ClubCount from
(
select p.ClubID,p.ShortCode,p.Keyword,p.ID
from dbo.Products p
union all
select p.ClubID,p.ShortCode,PAK.Keyword,PAK.ID * -1
from dbo.ProductAdditionalKeywords as PAK
inner join dbo.Products P on PAK.ProductID = P.ID
) as FullList
group by Shortcode,Keyword
order by Shortcode,Keyword
How I would normally do this would be to place all of the keywords in a separate table (e.g. what is currently your additional table). If all keywords must be distinct within a ShortCode, then I'd include ShortCode in this table also, so that a unique constraint can be applied across both columns.
If all keywords for a product must be in the same ShortCode, then I'd keep ShortCode in Products also. I'd apply a unique constraint on (ID,ShortCode) in that table, and an additional foreign key from the keywords table, referencing both columns on both sides.
What we're left with now are two potential issues not included in your original design, but I don't know if they're a concern in practice:
1) Is the Keyword in Products more important, or special, than the additional keywords? If so, we need to add a column to keywords table to mark which one is important. To ensure only one is set, you can search for plenty of other SO questions which involve unique constraints with additional conditions. (Let me know if you can't find one and need it, I'm sure I can add a link if necessary)
2) Should a Product be allowed to have no keywords? If not, then I'd create a view that mimics your original Products table. In this circumstance, it would be easier if 1) above is true, in which case we always join to the "important" keyword. Otherwise, we need to have some way to limit it to a single row per product. We deny insert/update/delete on the table, and only allow them through the view. 3 relatively simple triggers will then maintain the underlying table structure.
on your design, I do not understand the the use of productAdditionalShortCodes having no field of ShortCode.
However, you can add Unique key constraint with ShortCode & Keyword (composite key). This will eliminate duplicate entry in product table.