Updating both rows and columns in oracle - sql

Can rows be upadted along with the colums for a table.
I had a table where amount was to be updated for single member for 3 different years
I used the following query
update ahd
set amount1=(select a.amnt1
from ahd inner join ahdtmp a on ahd.member_key=a.member_key
where ahd.date1=a.date1
and a.status='FALSE'
and a.member_key in (select distinct member_key
from ahd))
When I execute this
ERROR at line 2:
ORA-01427: single-row subquery returns more than one row
The temporary table is ahdtmp
create table ahdtmp(
member_key number(10),
date1 date,
amnt1 number(10,2),
amnt2 number(10,2),
date_amend date,
Status varchar2(10));
Please suggest on this?
What could have gone wrong..

Possibly what you want is:
update ahd
set amount1=(select a.amnt1
from ahdtmp a
where ahd.member_key=a.member_key and
ahd.date1 =a.date1
and a.status='FALSE')
where member_key = 'some particlar member ey'

Maybe the following script will be useful, is a generic code (its only an example):
CREATE TABLE SOURCE(
s_key int,
s_name varchar2(100));
CREATE TABLE TARGET(
t_key int,
t_name varchar2(100));
INSERT INTO SOURCE VALUES(1,'A');
INSERT INTO SOURCE VALUES(2,'B');
INSERT INTO SOURCE VALUES(3,'C');
INSERT INTO SOURCE VALUES(4,'D');
INSERT INTO TARGET VALUES(1,'Z');
INSERT INTO TARGET VALUES(2,'Z');
INSERT INTO TARGET VALUES(3,'Z');
INSERT INTO TARGET VALUES(4,'Z');
/*HERE THE CODE*/
MERGE
INTO target
USING (
SELECT s.s_name,s.s_key
FROM source s
)
ON (t_key = s_key)
WHEN MATCHED THEN
UPDATE
SET t_name = s_name;
Here the link to try this example (it works fine) sql fiddle.
I not sure but your query would be something like this:
MERGE
INTO ahd
USING (
SELECT a.amnt1
FROM ahdtmp a
)
ON (ahd.member_key=a.member_key)
WHEN MATCHED THEN
UPDATE
SET amount1 = amnt1
WHERE ahd.status='FALSE'
AND ahd.member_key IN (SELECT DISTINCT member_key FROM ahd);

Issue here is sub query returns multiple values. You have to filter it to return single record.
update ahd
set amount1=(select a.amnt1
from ahd inner join ahdtmp a on ahd.member_key=a.member_key
where ahd.date1=a.date1
and a.status='FALSE'
and a.member_key ='user_specific_key')

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

SQL Merge not inserting new row

I am trying to use T-SQL Merge to check for the existence of records and update, if not then insert.
The update works fine, but the insert is not working.
Any and all help on this would be gratefully received.
DECLARE
#OperatorID INT = 2,
#CurrentCalendarView VARCHAR(50) = 'month';
WITH CTE AS
(
SELECT *
FROM dbo.OperatorOption
WHERE OperatorID = #OperatorID
)
MERGE INTO OperatorOption AS T
USING CTE S ON T.OperatorID = S.OperatorID
WHEN MATCHED THEN
UPDATE
SET T.CurrentCalendarView = #CurrentCalendarView
WHEN NOT MATCHED BY TARGET THEN
INSERT (OperatorID, PrescriptionPrintingAccountID, CurrentCalendarView)
VALUES (#OperatorID, NULL, #CurrentCalendarView);
When would a row Selected from OperatorOption not already exist in OperatorOption?
If you're saying this code does not insert - you're right it doesn't because the row has to be there to begin with (in which case it won't insert), or the row is not there to begin with, in which case there is nothing in the source dataset to insert.
Does
SELECT *
FROM dbo.OperatorOption
WHERE OperatorID = #OperatorID
return anything or not?
This does not work the way you think it does. There is nothing in the source CTE.
The answer to 'was a blank dataset missing from the target' is 'No' so nothing is inserted
To do this operation, I use this construct:
INSERT INTO dbo.OperatorOption
(OperatorID, PrescriptionPrintingAccountID, CurrentCalendarView)
SELECT #OperatorID, NULL, #CurrentCalendarView
WHERE NOT EXISTS (
SELECT * FROM dbo.OperatorOption
WHERE OperatorID = #OperatorID
)
It does not matter you are inserting values as variables. It thinks there is nothing to insert.
You need to produce data that does not match.
Like this:
DECLARE #OperatorID INT = 3, #CurrentCalendarView VARCHAR(50) = 'month';
declare #t table (operatorID int, CurrentCalendarView varchar(50));
insert into #t values (2, 'year');
MERGE #t AS TARGET
USING (SELECT #OperatorID, #CurrentCalendarView) AS source (operatorID, CurrentCalendarView)
on (TARGET.operatorID = Source.operatorID)
WHEN MATCHED THEN
UPDATE SET TARGET.CurrentCalendarView = #CurrentCalendarView
WHEN NOT MATCHED BY TARGET THEN
INSERT (OperatorID, CurrentCalendarView)
VALUES (source.OperatorID, source.CurrentCalendarView);
select * from #t
Insert probably isn't working because your source CTE does not produce any rows. Depending on how your table is organised, you might need to select from some other source, or use table valued constructor to produce source data.

Does sqlite has something like case on procedural Level?

I have a simple, as it looks, question:
I am having Sqlite query where I am using temp tables and then joining those table, something like:
drop table if exists SourceA
create temp table SourceA (id int, value text);
insert into SourceA select id, value from TableA
drop table if exists SourceB
create temp table SourceB (id int, value text);
insert into SourceB select id, value from TableB
select SourceA.*, SourceB.* from SourceA join SourceB on SourceA.id = SourceB.id
Now is it possible to create some sort of procedura if or case so for example one of those insert will not be executed, like:
bool merge = false;
drop table if exists SourceA
create temp table SourceA (id int, value text);
insert into SourceA select id, value from TableA
if(merge)
{
drop table if exists SourceB
create temp table SourceB (id int, value text);
insert into SourceB select id, value from TableB
select SourceA.*, SourceB.* from SourceA join SourceB on SourceA.id = SourceB.id
else
{
select * from SourceA
}
Example of usage is simple, its like a condition when you determine seconds two dates, let's say second table counts missing seconds, so now if interval is too big app will crush. So i need to determine outside of SQL if such thing can be done, and pass it to SQL (basically it can be any condition that will exclude second insert from happening)
I've mange to handle my problem by using variables temp table like:
drop table if exists Variables;
create temp table Variables (MinDatetime Datetime, MaxDatetime Datetime);
insert into Variables Values(#MinDatetime, #MaxDatetime);
And then passing parameter from code, an just omitting result using case something like:
case when (Select MinDatetime from Variables) = 'None' or (Select MaxDatetime from Variables) = 'None' then 0
else value
end as value
And if value is 'None' it will return just plain 0
SQLite is designed as an embedded database, to be used together with a 'real' programming language, so it does not have any procedural features.
Put the control logic into your actual program (or, if you don't have one, write a script).

Database inner join update

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)