How to use nested Insert based on select statement using ms sql server - sql-server-2012

I have multiple records in Select statement, I want to insert these records in two different tables based on Primary keys.
I have three tables Roles, MenuMaster and MenuChild as under
Roles:
- RoleID(PK) RoleName
- 1 Sales
- 2 Marketing
- 3 IT
MenuMaster:
- MID(PK) MFormName RoleID(FK)
- 1 Orders 1
- 2 SMM 2
- 3 Help 1
MenuChild:
- CID(PK) FormName, MID(FK)
- 1 NewOrder.aspx 1
- 2 RepeatOrder.aspx 1
- 3 Advertise.aspx 2
I want to create a new merge Role like '4, Sales & Marketing' and copy all records of RoleID=1 and RoleID=2 from MenuMaster to 'Sales & Marketing' RoleID and copy MenuChild record against new Inserted record MenuID

Create the role and use a temp table to populate the other tables:
INSERT INTO dbo.Roles (RoleName)
VALUES ('Sales & Marketing')
SELECT
'Sales & Marketing' as RoleName,
mm.MenuId,
mm.MFormName,
SCOPE_IDENTITY() AS PK
INTO #tmp
FROM dbo.MenuMaster mm
WHERE mm.RoleId in (1,2)
INSERT INTO dbo.MenuMaster (MFormName, RoleId)
SELECT t.MFormName, t.PK from #tmp t
UPDATE #tmp SET PK = SCOPE_IDENTITY()
INSERT INTO dbo.MenuChild(FormName, MenuId)
SELECT t.MFormName, t.PK from #tmp t
This is a little ugly because I'm not sure I completely understood your requirement. You can also use a CTE, but after the first INSERT into MenuMaster, you will need to create another CTE

Related

SQL Server find unique combinations

I have a table
rate_id service_id
1 1
1 2
2 1
2 3
3 1
3 2
4 1
4 2
4 3
I need to find and insert in a table the unique combinations of sevice_ids by rate_id...but when the combination is repeated in another rate_id I do not want it to be inserted
In the above example there are 3 combinations
1,2 1,3 1,2,3
How can I query the first table to get the unique combinations?
Thanx!
Try doing something like this:
DECLARE #TempTable TABLE ([rate_id] INT, [service_id] INT)
INSERT INTO #TempTable
VALUES (1,1),(1,2),(2,1),(2,3),(3,1),(3,2),(4,1),(4,2),(4,3)
SELECT DISTINCT
--[rate_id], --include if required
(
SELECT
CAST(t2.[service_id] AS VARCHAR) + ' '
FROM
#TempTable t2
WHERE
t1.[rate_id] = t2.[rate_id]
ORDER BY
t2.[rate_id]
FOR XML PATH ('')
) AS 'Combinations'
FROM
#TempTable t1
I put the values in a table variable just for ease of testing the SELECT query.

inserting data in table in sql from another table records

I have 2 tables...
UserMaster (UserID, Fname)
SharingMaster (SharingID, UserID)
I want all data inserted into SharingMaster that UserID are available in UserMaster... means each row per userid from usermaster....
For example.. if I have data in both tables
UserMaster:
UserID Fname
-----------------------
1 Abc
4 Def
5 asda
8 fgdfgdf
and SharingMaster as follows
SharingID UserID
-------------------------
6 1
9 4
8 5
8 8
so what is query for that?
If you're trying to insert UserIDs into SharingMaster from UserMaster that are not already present, here's a way to do it in SQL Server. My only assumption is that the SharingID is an IDENTITY column that will auto populate.
INSERT INTO dbo.SharingMaster
(UserID
, Fname
)
SELECT UserID
, Fname
FROM UserMaster
WHERE NOT EXISTS ( SELECT 1
FROM SharingMaster
WHERE SharingMaster.UserID = UserMaster.UserID )
Then again, since the scenario was a little ambiguous, here are some other options. My assumption here is that "all the data" you referred to was the Fname column from UserMaster.
If you wanted to insert or overwrite existing data for IDs already in sharing master:
INSERT INTO SharingMaster
(Fname
)
SELECT Fname
FROM UserMaster
JOIN SharingMaster
ON UserMaster.UserID = SharingMaster.SharingID
And as a bonus, if you're on SQL Server 2008 R2 or above, you can use the MERGE statement:
MERGE dbo.SharingMaster AS TARGET
USING
(SELECT UserID
, Fname
FROM dbo.UserMaster
) AS SOURCE (UserID, Fname)
ON (TARGET.UserID = SOURCE.UserID)
WHEN MATCHED
THEN
UPDATE SET
Fname = SOURCE.Fname
WHEN NOT MATCHED
THEN
INSERT (UserID, Fname)
VALUES
(SOURCE.UserID
, SOURCE.Fname
);

SQL 2008: Insert multiple rows based on specific criteria

I am trying to clone user permissions. The permissions are driven from a table with only 2 columns, userid and groupid. Both are foreign keys.
Is it possible to insert multiple rows based on criteria? Let's say:
USERID GROUPID
1 A
1 B
1 C
1 D
I would like to insert rows to give USER 2 the same GROUPS as USER 1.
Does this get me close?
INSERT INTO ide_usergroup_assoc (userid, groupid)
VALUES ('USERID I PROVIDE', (SELECT ide_usergroup_assoc.groupid from ide_usergroup_assoc WHERE ide_usergroup_assoc.userid = 'USERID TO BE CLONED'))
insert into ide_usergroup_assoc (userid, groupid)
select 2, groupid
from ide_usergroup_assoc
where userid = 1

Updating Uncommitted data to a cell with in an UPDATE statement

I want to convert a table storing in Name-Value pair data to relational form in SQL Server 2008.
Source table
Strings
ID Type String
100 1 John
100 2 Milton
101 1 Johny
101 2 Gaddar
Target required
Customers
ID FirstName LastName
100 John Milton
101 Johny Gaddar
I am following the strategy given below,
Populate the Customer table with ID values in Strings Table
INSERT INTO CUSTOMERS SELECT DISTINCT ID FROM Strings
You get the following
Customers
ID FirstName LastName
100 NULL NULL
101 NULL NULL
Update Customers with the rest of the attributes by joining it to Strings using ID column. This way each record in Customers will have corresponding 2 matching records.
UPDATE Customers
SET FirstName = (CASE WHEN S.Type=1 THEN S.String ELSE FirstName)
LastName = (CASE WHEN S.Type=2 THEN S.String ELSE LastName)
FROM Customers
INNER JOIN Strings ON Customers.ID=Strings.ID
An intermediate state will be llike,
ID FirstName LastName ID Type String
100 John NULL 100 1 John
100 NULL Milton 100 2 Milton
101 Johny NULL 101 1 Johny
101 NULL Gaddar 101 2 Gaddar
But this is not working as expected. Because when assigning the values in the SET clause it is setting only the committed values instead of the uncommitted. Is there anyway to set uncommitted values (with in the processing time of query) in UPDATE statement?
PS: I am not looking for alternate solutions but make my approach work by telling SQL Server to use uncommitted data for UPDATE.
The easiest way to do it would be to split the update into two:
UPDATE Customers
SET FirstName = Strings.String
FROM Customers
INNER JOIN Strings ON Customers.ID=Strings.ID AND Strings.Type = 1
And then:
UPDATE Customers
SET LastName = Strings.String
FROM Customers
INNER JOIN Strings ON Customers.ID=Strings.ID AND Strings.Type = 2
There are probably ways to do it in one query such as a derived table, but unless that's a specific requirement I'd just use this approach.
Have a look at this, it should avoid all the steps you had
DECLARE #Table TABLE(
ID INT,
Type INT,
String VARCHAR(50)
)
INSERT INTO #Table (ID,[Type],String) SELECT 100 ,1 ,'John'
INSERT INTO #Table (ID,[Type],String) SELECT 100 ,2 ,'Milton'
INSERT INTO #Table (ID,[Type],String) SELECT 101 ,1 ,'Johny'
INSERT INTO #Table (ID,[Type],String) SELECT 101 ,2 ,'Gaddar'
SELECT IDs.ID,
tName.String NAME,
tSur.String Surname
FROM (
SELECT DISTINCT ID
FROM #Table
) IDs LEFT JOIN
#Table tName ON IDs.ID = tName.ID AND tName.[Type] = 1 LEFT JOIN
#Table tSur ON IDs.ID = tSur.ID AND tSur.[Type] = 2
OK, i do not think that you will find a solution to what you are looking for. From UPDATE (Transact-SQL) it states
Using UPDATE with the FROM Clause
The results of an UPDATE statement are
undefined if the statement includes a
FROM clause that is not specified in
such a way that only one value is
available for each column occurrence
that is updated, that is if the UPDATE
statement is not deterministic. For
example, in the UPDATE statement in
the following script, both rows in
Table1 meet the qualifications of the
FROM clause in the UPDATE statement;
but it is undefined which row from
Table1 is used to update the row in
Table2.
USE AdventureWorks;
GO
IF OBJECT_ID ('dbo.Table1', 'U') IS NOT NULL
DROP TABLE dbo.Table1;
GO
IF OBJECT_ID ('dbo.Table2', 'U') IS NOT NULL
DROP TABLE dbo.Table2;
GO
CREATE TABLE dbo.Table1
(ColA int NOT NULL, ColB decimal(10,3) NOT NULL);
GO
CREATE TABLE dbo.Table2
(ColA int PRIMARY KEY NOT NULL, ColB decimal(10,3) NOT NULL);
GO
INSERT INTO dbo.Table1 VALUES(1, 10.0), (1, 20.0), (1, 0.0);
GO
UPDATE dbo.Table2
SET dbo.Table2.ColB = dbo.Table2.ColB + dbo.Table1.ColB
FROM dbo.Table2
INNER JOIN dbo.Table1
ON (dbo.Table2.ColA = dbo.Table1.ColA);
GO
SELECT ColA, ColB
FROM dbo.Table2;
Astander is correct (I am accepting his answer). The update is not happening because of a read UNCOMMITTED issue but because of the multiple rows returned by the JOIN. I have verified this. UPDATE picks only the first row generated from the multiple records to update the original table. This is the behavior for MSSQL, Sybase and such RDMBMSs but Oracle does not allow this kind of an update an d it throws an error. I have verified this thing for MSSQL.
And again MSSQL does not support updating a cell with UNCOMMITTED data. Don't know the status with other RDBMSs. And I have no idea if anyRDBMS provides with in the query ISOLATION level management.
An alternate solution will be to do it in two steps, Aggregate to unpivot and then insert. This has lesser scans compared to methods given in above answers.
INSERT INTO Customers
SELECT
ID
,MAX(CASE WHEN Type = 1 THEN String ELSE NULL END) AS FirstName
,MAX(CASE WHEN Type = 2 THEN String ELSE NULL END) AS LastName
FROM Strings
GROUP BY ID
Thanks to my friend Roji Thomas for helping me with this.

mySQL inserting multiple records with a select

I have a "dictionary table" called car_status that has an 'id' column and a 'status' column.
car_status
id status
1 broken
2 fixed
3 working
4 fast
5 slow
I have a table called cars with the columns: id, type, status_id
cars
id type status_id
1 jeep 1
2 ford 3
3 acura 4
I am hoping to insert multiple records into cars and give them all the status associated with "working". What is the best/ easiest way? I know I can query and find the status_id that is "working", and then do an insert query, but is there anyway to do it with one insert query using a join or select?
I tried stuff like:
INSERT INTO cars (type, status_id)
VALUES
('GM',status_id),
('Toyota',status_id),
('Honda',status_id)
SELECT id as status_id
FROM car_status
WHERE status = "working"
Thanks!
DECLARE temp_status_id INT;
SELECT status_id
INTO temp_status_id
FROM car_status;
INSERT INTO cars (type, status_id)
VALUES ('GM',temp_status_id),
('Toyota',temp_status_id),
('Honda',temp_status_id);
This is MS SQL, but I think you can do something like this:
DECLARE #status_id int
SELECT #status_id = status_id FROM car_status WHERE status = 'working'
INSERT INTO cars (type, status_id)
SELECT 'GM', #status_id
UNION
SELECT 'Toyota', #status_id
UNION...
Is there some reason you want to do it in a single statement? Personally, I'd just write an insert statement for each row. I guess you could also create a temp table with all the new types and then join that with the status id.