Database inner join update - sql

I am trying to update a table column from a table column in another table and am using the following code - it generates the error below.
Any ideas?
UPDATE URLRecord
  SET URLRecord.Slug = aaNewURLSlugss.NewSlugName
FROM URLRecord
INNER JOIN aaNewURLSlugs ON URLRecord.Slug = aaNewURLSlugss.OldSlugName
Error:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near ','.

SQL Server doesn't like the qualified column name in SET. Does this work?
UPDATE r
SET Slug = n.NewSlugName
FROM URLRecord r inner join
aaNewURLSlugs n
ON r.Slug = n.OldSlugName;
The error message would be different, though, from what you are getting. This would be an additional error.

Here is a working solution that uses a temporary table. It may not be ideal and I've included some drop statements, so don't run this on your production machine.
-- Build our test tables
CREATE TABLE [URLRecord]
(
[Id] INTEGER IDENTITY PRIMARY KEY,
[Slug] CHARACTER VARYING(255) NOT NULL
)
GO
CREATE TABLE [NewSlugs]
(
[Id] INTEGER IDENTITY PRIMARY KEY,
[NewSlugName] CHARACTER VARYING(255) NULL,
[OldSlugName] CHARACTER VARYING(255) NULL
)
GO
-- Insert test data
INSERT INTO [URLRecord] VALUES ('Original Name');
INSERT INTO [NewSlugs] VALUES ('New Name', 'Original Name');
-- Populate work table with the records we want to modify
SELECT [URLRecord].[Id], [NewSlugs].[NewSlugName] INTO #SlugWork
FROM [URLRecord]
INNER JOIN [NewSlugs] ON [URLRecord].[Slug] = [NewSlugs].[OldSlugName]
-- We're just echoing here
SELECT * FROM #SlugWork
-- Pull everything from our temporary table and update modified records
UPDATE [URLRecord]
SET [URLRecord].[Slug] = [T].[NewSlugName]
FROM #SlugWork AS [T]
WHERE [T].[Id] = [URLRecord].[Id]
-- Proving it's updated
SELECT * FROM [URLRecord]
-- Drop our example stuff, for rerunnability
DROP TABLE #SlugWork
DROP TABLE [NewSlugs]
DROP TABLE [URLRecord]

Try using Aliases
UPDATE A
SET A.Slug = B.NewSlugName
FROM URLRecord AS A
INNER JOIN aaNewURLSlugs B
ON A.Slug = B.OldSlugName

Try to use embedded sql like this:
UPDATE URLRecord
SET Slug = (
SELECT NewSlugName
FROM aaNewURLSlugs
WHERE URLRecord.Slug = aaNewURLSlugs.OldSlugName )
WHERE Slug IN (SELECT OldSlugName FROM aaNewURLSlugs)

Related

Why is this temporary table throwing an error about the number of column supplied?

I'm trying to run this specific code for a temp table, but somehow I get this error
Column name or number of supplied values does not match table definition
What's wrong?
DROP TABLE IF EXISTS #GamesDistribution
CREATE TABLE #GamesDistribution
(
Platform nvarchar(255),
Name nvarchar(255),
NA_Sales numeric,
EU_Sales numeric,
JP_Sales numeric
)
INSERT INTO #GamesDistribution
SELECT
properties.Platform,
properties.Name,
revenue.NA_Sales,
revenue.EU_Sales,
revenue.JP_Sales
FROM
games_properties AS Properties
JOIN
games_revenue AS Revenue ON properties.Game_ID = Revenue.Game_ID
--GROUP BY properties.platform
--ORDER BY Total_Games DESC, Total_NA_Sales DESC, Total_EU_Sales DESC, Total_JP_Sales DESC;
The problem here is that prior to you running your batch the table already exists. As such when the batch is parsed, by the compiler, the compilation fails; because the number of columns doesn't match that of the table already exists.
This can be replicated with the following:
CREATE TABLE #t (I int);
INSERT INTO #t (I)
VALUES(1);
GO
DROP TABLE IF EXISTS #t;
CREATE TABLE #t (I int, D date);
INSERT INTO #t
VALUES(2,GETDATE());
GO
SELECT *
FROM #t;
GO
DROP TABLE #t
db<>fiddle
This returns the error:
Msg 213, Level 16, State 1, Line 10
Column name or number of supplied values does not match table definition.
And the dataset:
I
1
This is because the 2nd batch, with the DROP TABLE IF EXISTS never ran; the compilation failed.
The "simple" solution here would be to put your DROP IF EXISTS in a separate batch, and also specify your columns:
DROP TABLE IF EXISTS #GamesDistribution;
GO
CREATE TABLE #GamesDistribution (Platform nvarchar(255),
Name nvarchar(255),
NA_Sales numeric, --Where is your precision and scale?
EU_Sales numeric, --Where is your precision and scale?
JP_Sales numeric); --Where is your precision and scale?
INSERT INTO #GamesDistribution (Platform,Name, NA_Sales,EU_Sales,JP_Sales)
SELECT properties.Platform,
properties.Name,
revenue.NA_Sales,
revenue.EU_Sales,
revenue.JP_Sales
FROM dbo.games_properties AS Properties
JOIN dbo.games_revenue AS Revenue ON properties.Game_ID = Revenue.Game_ID;
You can actually do this way
DROP TABLE IF EXISTS #GamesDistribution
SELECT properties.Platform,
properties.Name,
revenue.NA_Sales,
revenue.EU_Sales,
revenue.JP_Sales
INTO #GamesDistribution
FROM games_properties AS Properties
JOIN games_revenue AS Revenue
ON properties.Game_ID = Revenue.Game_ID
and then you can check the columns' data types of the temp table:
EXEC tempdb..sp_help '#GamesDistribution'
SELECT *
FROM tempdb.sys.columns
WHERE [object_id] = OBJECT_ID('tempdb..#GamesDistribution');
Note: It's always better to ensure the columns' data types. Your query might list different columns' data types.
Add GO statement under drop table as below.
DROP TABLE IF EXISTS #GamesDistribution
GO
CREATE TABLE #GamesDistribution
(
.
.
.

variables in complex sql queury/rule

I want to insert values into a view, which is over multiple tables. I use Postgresql.
My solution is to write a rule which inserts all the data into the right table and adds the foreign keys into the rows.
My question is: Can I somehow declare variables into the rule for recurring select-statements?
The code for the rule is:
create rule insert_new_user as on insert to "collHBRS".loginview do instead(
-- add email_address to email table
insert into "collHBRS".email(email_addr) values (new.login_name);
-- add new empty profile to profile table
insert into "collHBRS".profile(profile_email_fk, profile_address_fk, profile_student_fk, profile_company_fk)
VALUES (
(select email_id from "collHBRS".email where email_addr = new.login_name), -- get email_fk
null,null,null);
-- create new login
insert into "collHBRS".login(login_email_fk, login_password, login_salt, last_login, login_profile_fk)
values (
(select email_id from "collHBRS".email where email_addr = new.login_name), -- get email_fk
new.login_password,new.login_salt,now(),
(select profile_id from "collHBRS".profile where profile_email_fk =
(select email_id from "collHBRS".email where email_addr = new.login_name) -- get profile_fk with email_fk
)
)
);
I repeat the select-statement to get the primary key from my new email entry like 2 times.
(select email_id from "collHBRS".email where email_addr = new.login_name)
I tried it, with DECLARE and WITH AS.
The rule works, it is just not pretty.
Thank you

Merge sql throws Unique constraint violation error

I have below two table for which when i query table TEST_RUA:
select CLASS, ID_LL, ID_UU, TKR from TEST_RUA where ID_UU= 'GV9999B12M0'
it returns:
CLASS ID_LL ID_UU TKR
Bond (null) GV9999B12M0 WIB
When i query table TEST_RUA_MER:
select CLASS, ID_LL, ID_UU, TKR from TEST_RUA_MER where ID_UU= 'GV9999B12M0'
it returns:
CLASS ID_LL ID_UU TKR
Bond (null) GV9999B12M0 WIB
You can see both the values are same for table where ID_UU= 'GV9999B12M0'. The table TEST_RUA_MER has unique index on columns ID_LL, ID_UU, TKR.
Now i have below merge query which throws error as ORA-00001: unique constraint violated and i dont understand how can i avoid this error as both the table values are same then in this case this merge query should try to update and not to insert in table TEST_RUA_MER .
merge into TEST_RUA_MER h using (
select distinct r.CLASS, r.ID_LL, r.ID_UU, r.TKR from TEST_RUA r ) s
on (s.ID_LL=h.ID_LL and s.ID_UU=h.ID_UU and s.TKR=h.TKR) when matched then
update set h.CLASS = s.CLASS, h.ID_LL = s.ID_LL, h.ID_UU = s.ID_UU, h.TKR = s.TKR
when not matched then insert values (s.CLASS, s.ID_LL, s.ID_UU, s.TKR);
Looks like NULL causes problems; it isn't "equal" to anything, so this:
on (s.ID_LL=h.ID_LL
fails.
Try with
on (nvl(s.ID_LL, -1) = nvl(h.ID_LL, -1)
(depending on what ID_LL column's datatype is; I presumed it is a number).
Yes, As mentioned in the other answer also, cause of the error is s.ID_LL=h.ID_LL. You can update it as
( s.ID_LL=h.ID_LL OR (s.ID_LL is null and h.ID_LL is null) )
OR
( s.ID_LL=h.ID_LL OR coalesce(s.ID_LL, h.ID_LL) is null )

Scalar Variable error using var Table but not Temp Table

I am stumped with this one. I have the following code it works fine up to the point of the last #POC_XLATE in the update statement and then I get the error MUST DECLARE SCALAR VARIABLE.
If I change the table to a temp table the code works fine. I have tried moving the select statement to the end of the code, that didn't work. Hope someone has some suggestion on why it is doing this. Thanks in advance.
declare #POC_XLATE as TABLE(
POC_XLATE_ID int NULL,
TAR_ID int NULL,
POC_USERID varchar(50) NULL,
ACTION_DATE datetime NULL
)
insert into #POC_XLATE(POC_XLATE_ID, TAR_ID, POC_USERID, ACTION_DATE)
select * from POC_XLATE
where POC_XLATE.ACTION_DATE is null
select * from #POC_XLATE
update #POC_XLATE
set ACTION_DATE = TAR_DATA.OPEN_DATE
from TAR_DATA
where #POC_XLATE.TAR_ID = TAR_DATA.TAR_ID
A column alias cannot start with a #. That is the sign for a declared scalar variable. So, use table aliases:
update p
set ACTION_DATE = td.OPEN_DATE
from #POC_XLATE p JOIN
TAR_DATA td
on p.TAR_ID = td.TAR_ID ;
But why you would write the query in two steps?
insert into #POC_XLATE(POC_XLATE_ID, TAR_ID, POC_USERID, ACTION_DATE)
select p.POC_XLATE_ID, p.TAR_ID, p.POC_USERID, td.OPEN_DATE
from POC_XLATE p left join
TAR_DATA td
on p.TAR_ID = td.TAR_ID
where p.ACTION_DATE is null;
One step is much cleaner than two.

Update Statement Fails

I have a table called [dbo].[ProductComponentRelationship] with 4 fields
[ProductComponentRelationshipID] PK, INt, Not Null
[ProductItemID] FK, Int Not Null
[ComponentItemID] FK, Int, Not Null
[SequenceNumber] int null
This table houses a bunch of values. I need to update 4000 records in the table above. Therefore i populated a seperate table with a productItemID, and the new ComponentitemID value. I tried to run the sql statement below and it failed:
update ProductComponentRelationship set ComponentItemID =
(select compid from cst_pricefix where
ProductComponentRelationship.ProductItemID = cst_pricefix.prditem and
ProductComponentRelationship.ProductComponentRelationshipID = ProductComponentRelationship.ProductComponentRelationshipID )
Error Message:
Msg 515, Level 16, State 2, Line 1
Cannot insert the value NULL into column 'ComponentItemID', table 'SDSDB.dbo.ProductComponentRelationship'; column does not allow nulls. UPDATE fails.
If this is SQL Server, which it looks like from the dbo, you can update over a join like so:
update
pcr
set
ComponentItemID = f.compid
from
ProductCompnentRelationship pcr
inner join
cst_pricefix f
on pcr.ProductItemID = f.prditem
I'm not sure what ProductComponentRelationship.ProductComponentRelationshipID = ProductComponentRelationship.ProductComponentRelationshipID was about in your original query, so there may be something missing from mine.