Insert row over existing row, move rows down - sql

I'm trying to insert a new row in the middle of a sql table and move all other rows first to make space for it.
I've tried
setting id=id+1,
but that gives me an error(obviously) because the row id+1 exists already, so this only works for going in the other direction so id=id-1.
What is the correct solution then?

To do the stuff, you should update you table from the end:
UPDATE `table` SET `id`=`id`+1 WHERE `id`>$value ORDER BY `id` DESC
Where $value is your value

You could try something like this:
UPDATE table_name SET id = id + 1 WHERE id >= your_id_value ORDER BY id DESC;
INSERT INTO table_name(..., id, ...) VALUES(..., your_id_value, ...)

Related

Can I hard code a value into column in the SELECT clause

I want to populate column SURVEY_TYPE_ID with 1
Can I do this like so?
SELECT
SURVEY_ID,
SKILL_ID,
1 AS SURVEY_TYPE_ID,
From Table A
This should work as it is:
SELECT
SURVEY_ID,
SKILL_ID,
1 AS SURVEY_TYPE_ID
From Table A
Also, if you want to populate string in the column value just add quotes.
SELECT
SURVEY_ID,
SKILL_ID,
'id_123' AS SURVEY_TYPE_ID
From Table A
This query returns a result set with a third column whose value is 1:
SELECT SURVEY_ID, SKILL_ID, 1 AS SURVEY_TYPE_ID
FROM Table_A
(This is the same as your query with the spurious comma removed.)
If you want to change the value of the column in the table, then you need UPDATE:
UPDATE Table_A
SET SURVEY_TYPE_ID = 1;
If you want to add a new column to the table, then the syntax varies depending on the database, but generally something like this:
ALTER Table_A ADD COLUMN SURVEY_TYPE_ID INT DEFAULT 1;

Update columns in DB2 using randomly chosen static values provided at runtime

I would like to update rows with values chosen randomly from a set of possible values.
Ideally I would be able to provide this values at runtime, using JdbcTemplate from Java application.
Example:
In a table, column "name" can contain any name. The goal is to run through the table and change all names to equal to either "Bob" or "Alice".
I know that this can be done by creating a sql function. I tested it and it was fine but I wonder if it is possible to just use simple query?
This will not work, seems that the value is computed once, and applied to all rows:
UPDATE test.table
SET first_name =
(SELECT a.name
FROM
(SELECT a.name, RAND() idx
FROM (VALUES('Alice'), ('Bob')) AS a(name) ORDER BY idx FETCH FIRST 1 ROW ONLY) as a)
;
I tried using MERGE INTO, but it won't even run (possible_names is not found in SET query). I am yet to figure out why:
MERGE INTO test.table
USING
(SELECT
names.fname
FROM
(VALUES('Alice'), ('Bob'), ('Rob')) AS names(fname)) AS possible_names
ON ( test.table.first_name IS NOT NULL )
WHEN MATCHED THEN
UPDATE SET
-- select random name
first_name = (SELECT fname FROM possible_names ORDER BY idx FETCH FIRST 1 ROW ONLY)
;
EDIT: If possible, I would like to only focus on fields being updated and not depend on knowing primary keys and such.
Db2 seems to be optimizing away the subselect that returns your supposedly random name, materializing it only once, hence all rows in the target table receive the same value.
To force subselect execution for each row you need to somehow correlate it to the table being updated, for example:
UPDATE test.table
SET first_name =
(SELECT a.name
FROM (VALUES('Alice'), ('Bob')) AS a(name)
ORDER BY RAND(ASCII(SUBSTR(first_name, 1, 1)))
FETCH FIRST 1 ROW ONLY)
or may be even
UPDATE test.table
SET first_name =
(SELECT a.name
FROM (VALUES('Alice'), ('Bob')) AS a(name)
ORDER BY first_name, RAND()
FETCH FIRST 1 ROW ONLY)
Now that the result of subselect seems to depend on the value of the corresponding row in the target table, there's no choice but to execute it for each row.
If your table has a primary key, this would work. I've assumed the PK is column id.
UPDATE test.table t
SET first_name =
( SELECT name from
( SELECT *, ROW_NUMBER() OVER(PARTITION BY id ORDER BY R) AS RN FROM
( SELECT *, RAND() R
FROM test.table, TABLE(VALUES('Alice'), ('Bob')) AS d(name)
)
)
AS u
WHERE t.id = u.id and rn = 1
)
;
There might be a nicer/more efficient solution, but I'll leave that to others.
FYI I used the following DDL and data to test the above.
create table test.table(id int not null primary key, first_name varchar(32));
insert into test.table values (1,'Flo'),(2,'Fred'),(3,'Sue'),(4,'John'),(5,'Jim');

How can I iterate through SQL results like a for loop and an array?

I have a table, and I want to select only the single column of row IDs from it, but in a specific order. Then, I want to loop through that column like below:
for (i=0; i<rows.length; i++)
{
if(i==rows.length-1)
UPDATE myTable SET nextID = NULL WHERE ID = rows[i]
ELSE
UPDATE myTable SET nextID = rows[i+1] WHERE ID = rows[i]
}
I just dont know how to access the results of my select statement with an index like that. Is there a way of doing this in sql server?
Since you didn't provide many details, let's pretend your table looks something like this:
create table MyTable (
Id int not null primary key,
Name varchar(50) not null,
NextId int
)
I want to select only the single column of row IDs from it, but in a specific order
Let's just say that in this case, you decide to order the rows alphabetically by Name. So let's pretend that the select statement that you want to loop through looks like this:
select Id
from MyTable
order by Name
That being the case, instead of looping through the rows and attempting to update each row using the pseudo-code you provided, you can replace the whole thing with a single update statement that will perform the exact same work:
with cte as (
select *,
NewNextId = lead(Id) over (order by Name)
from MyTable
)
update cte
set NextId = NewNextId
Just make sure to adjust the order by clause to whatever your specific order really is. I just used Name in my example, but it might be something else in your case.
You could use a cursor, or you could use something a bit smarter.
Your example should be able to be written fairly easily along the lines of:
update mytable set nextID = LEAD(id,1) over (order by id)
Lead(id,1) will grab the next id, 1 row ahead in the record set and update the nextID field with it. If it can't find one it will return null. No looping or conditional logic needed!
edit: I forgot the over clause. This is the part that tells it how you would like it ordered for the lead

How to delete multiple rows in SQL where id = (x to y)

I am trying to run a SQL query to delete rows with id's 163 to 265 in a table
I tried this to delete less number of rows
DELETE FROM `table` WHERE id IN (264, 265)
But when it comes to delete 100's of rows at a time, Is there any query similar to above method
I am also trying to use this kind of query but failed to execute it
DELETE FROM `table` WHERE id IN (SELECT * FROM table WHERE id = )
Please tell me the query to do the above action...
If you need to delete based on a list, you can use IN:
DELETE FROM your_table
WHERE id IN (value1, value2, ...);
If you need to delete based on the result of a query, you can also use IN:
DELETE FROM your_table
WHERE id IN (select aColumn from ...);
(Notice that the subquery must return only one column)
If you need to delete based on a range of values, either you use BETWEEN or you use inequalities:
DELETE FROM your_table
WHERE id BETWEEN bottom_value AND top_value;
or
DELETE FROM your_table
WHERE id >= a_value AND id <= another_value;
You can use BETWEEN:
DELETE FROM table
where id between 163 and 265
Please try this:
DELETE FROM `table` WHERE id >=163 and id<= 265
SELECT * FROM your_table ORDER BY DESC
Get the range that you want to delete Ex: 3 to 10
DELETE FROM your_table
WHERE id BETWEEN 3 AND 10;
Make sure to add min value fist in BETWEEN Clause
CREATE PROC [dbo].[sp_DELETE_MULTI_ROW]
#CODE XML
,#ERRFLAG CHAR(1) = '0' OUTPUT
AS
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
DELETE tb_SampleTest
WHERE
CODE IN(
SELECT Item.value('.', 'VARCHAR(20)')
FROM #CODE.nodes('RecordList/ID') AS x(Item)
)
IF ##ROWCOUNT = 0
SET #ERRFLAG = 200
SET NOCOUNT OFF
Get string value delete
<RecordList>
<ID>1</ID>
<ID>2</ID>
</RecordList>

how to update a column for all rows in a table with different values for each row in a table of 100 records

my table contains 100 records and i need to update a column with new values(diff value for each record) for each of the 100 records .How can i do this. the column to update the values is not primary key.
UPDATE tablename
SET columnname = CASE id
WHEN 1 THEN 42
WHEN 2 THEN 666
END
With this query columnname will be updated to 42 for the row with id = 1, and 666 for id = 2
Create a table with an autoicrement id and the columns of the original table.
Then
INSERT INTO new_table (column1, column2,.....) -- refer all columns except autoincrement id
SELECT * FROM old_table
Update the old table by joining with the new, assuming the is a key composite or not that distincts each row
Set Unique constraint on this column.
ALTER TABLE YourTableName
ADD CONSTRAINT uc_ColumnID UNIQUE (ColumnName)
Now, whenever you try to update it with duplicate values, sql server will not allow:)
Also a long run scenario
If you're on SQL Server 2005 or newer (you didn't exactly specify.....), you could easily use a CTE (Common Table Expression) for this - basically, you select your PK value, and a counter counting up from 1, and you set each row's ColumnName column to the value of the counter:
;WITH UpdateData AS
(
SELECT
PKValue,
ROW_NUMBER() OVER(ORDER BY .......) AS 'RowNum'
FROM
dbo.YourTable
)
UPDATE dbo.YourTable
SET ColumnName = u.RowNum
FROM UpdateData u
WHERE dbo.YourTable.PKValue = u.PKValue
With this, you're generating a sequence from 1 through 100 in the RowNum field of the CTE, and you're setting this unique value to your underlying table.
load a DataTable say dt with specific row ID of the table which you wanna update.
then execute
foreach(DataRow rw in dt.Rows)
{
update table_name set column_name=desired_value where specific_column=rw
}