Copy SQL Server rows to new rows based on Where clause - sql

I am using SQL Server 2008. Assume I have a table structured like this (the below denotes the column names / types):
ID - Int (Primary Key) [This is set to autoincrement]
X - varchar(MAX)
Y - varchar(MAX)
Z - varchar(MAX)
I am trying to build a generic query that based on the a value of one of the columns, the query can copy the values of existing records into a new record, change some column values and naturally increment the ID. Consider the following pseudo code (I couldn't think of a way to distill this otherwise :/) :
1)
SELECT *
FROM TABLE
WHERE X = "Hello"
INTO TEMPTABLE
2)
COPY RESULTS
FROM TEMPTABLE
INTO TABLE
SET X = "HI HI HI" AND SET Y "HI!"
The expected result from the above would be the result set from 1) feeding the record creation in 2). The value of Z should be naturally copied over since we aren't setting it otherwise.

INSERT INTO foobar (x, y, z)
SELECT 'HI HI HI', 'HI!', z FROM foobar WHERE x = 'Hello'

Related

Replace value by fkey after moving data to related table

A numeric column should be extended to hold multiple values, i.e. reference some different entity. SQL only (Postgres specifically if no standard solution available).
Schema now:
Table X with columns ID, VAL, STUFF
Table Y with columns ID, VAL1, VAL2
What I want to achieve:
Table X with columns ID, YID, STUFF
Table Y won't be altered (neither existing data touched)
Table Y gets inserts for all rows of table X where X.VAL should be inserted as Y.VAL1. Y.ID auto-incremented, Y.VAL2 may remain NULL. Table X should then be updated to hold Y's ID as foreign key X.YID instead of the actual value X.VAL that is now stored in Y.VAL1.
Somehow I think it has to be possible to achieve that with a clean SQL-only solution. What I've found so far:
create some PG/SQL script: just loop over table X, insert the stuff to table Y row by row returning the ID and updating table X
plain SQL: get the number of entries in table Y, INSERT INTO Y with SELECT FROM X ... ORDER BY ID, INSERT INTO X with SELECT FROM Y ... skipping the number of entries that have been there before so the order should remain stable. I really don't like that solution. Sounds dirty to me.
Any suggestions? Or better go with PG/SQL?
TIA
There is a third option: a single SQL statement. Postgres allows DML within a CTE. So create a CTE that performs the insert and returns the generated id. Use the returned id in the main query which updates the original table. This then does what you are looking for in a single SQL statement.
with cte as
( insert into y(val1)
select val
from x
returning y.id, y.val1
)
update x
set val = cte.id
from cte
where x.val = cte.val1;
Then assuming you want to maintain referential integrity:
alter table x
add constraint x2y_fk
foreign key (val)
references y(id) ;
See Demo: Note: The demo copies both val and stuff from table x into table y. This was strictly for demonstration purposes and is not necessary.

Hive query to iterate and search the element

I have the below tables X and y table:
X table
column : Address
values : "ABCDHongKidoJapan589068".
I will be having 100 records like this
Y table
column :Name
Values :Hong
Timm
Agent
Lane.
I want to search if any of the Y values present in X, if present that values of Y will be stored in a different column name as Addr_nm in X table.
Can we achieve this in Hive. ?
I tried in python, but I have the requirement to do in the hive.

BQ - INSERT without listing columns

I have 2 BQ tables, very wide ones in terms of number of columns. Note all the table columns are made nullable for flexibility
Table A - 1000 cols - Superset of Bs cols
Table B - 500 cols - Subset of As cols - exactly named/typed as above cols
So rows in Bs table data should be insertable into A, where anything column not inserted just gets a null. i.e 500 cols get a value, remaining 500 get a default null as not present in the insert.
So as these tables are very wide, enumerating all the columns in an insert statement would take forever and be a maintence nightmare.
Is there a way in standard SQL to insert without listing the columns names in the the insert statement, whereby its automagically name matched?
So I want to be able to do this really and have the columns from B matched to A for each row inserted? If not is there any other way I am not seeing that could help with this?
thanks!
INSERT INTO
`p.d.A` (
SELECT
*
FROM
`p.d.B` )
I actually tried enumerating the columns to see if nesting worked and seems it doesnt?
INSERT INTO
`p.d.A` (x, y.z) (
SELECT
x, y.z
FROM
`p.d.B` )
I cant just say (x,y) as y structs from the dff tables arent exactly the same BQ complains structs dont match exact.....hence why I was trying y.z ?
Sure, easy!
Prepare dummy table p.d.b_ using below select
SELECT * FROM `p.d.a` WHERE FALSE
(Note, even though result will be empty table - above will scan whole table a - this is required just once - so should be Okey - if not you can script this once and just create this table from script)
Ok, so now instead of using
SELECT * FROM `p.d.b`
you will use
SELECT * FROM `p.d.b*`
and this will make a trick for you (it did for me :o)
P.S. Of course I assume you will make sure there is no other tables with names starting with b (or whatever real name is) in that dataset

Moving data from one column to another in PostgreSQL

Sometimes, one might want to move some data from one column to another. By moving (in constrast to copying), I mean that the new column was originally null before doing the operation, and the old column should be set to null after doing the operation.
I have a table defined as such:
CREATE TABLE photos(id BIGSERIAL PRIMARY KEY, photo1 BYTEA, photo2 BYTEA);
Suppose there is an entry in the table where photo1 contains some data, and photo2 is NULL. I would like to make an UPDATE query wuch that photo1 becomes NULL and photo2 contains the data that was originally in photo1.
I issue the following SQL command (WHERE clause left out for brevity):
UPDATE photos SET photo2 = photo1, photo1 = NULL;
It seems to work.
I also tried it this way:
UPDATE photos SET photo1 = NULL, photo2 = photo1;
It also seems to work.
But is it guaranteed to work? Specifically, could photo1 be set to NULL before photo2 is set to photo1, thereby causing me to end up with NULL in both columns?
As an aside, this standard UPDATE syntax seems inefficient when my BYTEAs are large, as photo2 has to be copied byte-by-byte from photo1, when a simple swapping of pointers might have sufficed. Maybe there is a more efficient way that I don't know about?
This is definitely safe.
Column-references in the UPDATE refer to the old columns, not the new values. There is in fact no way to reference a computed new value from another column.
See, e.g.
CREATE TABLE x (a integer, b integer);
INSERT INTO x (a,b) VALUES (1,1), (2,2);
UPDATE x SET a = a + 1, b = a + b;
results in
test=> SELECT * FROM x;
a | b
---+---
2 | 2
3 | 4
... and the ordering of assignments is not significant. If you try to multiply-assign a value, you'll get
test=> UPDATE x SET a = a + 1, a = a + 1;
ERROR: multiple assignments to same column "a"
because it makes no sense to assign to the same column multiple times, given that both expressions reference the old tuple values, and order is not significant.
However, to avoid a full table rewrite in this case, I would just ALTER TABLE ... ALTER COLUMN ... RENAME ... then CREATE the new column with the old name.

Rolling tables limited to a certian size (i.e. doing first in, first out on a table if its size is > y)

I have a database full of log entries that looks like this:
CREATE TABLE event_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
message VARCHAR(1024),
sent INTEGER DEFAULT 0
);
How would you go about limiting the size of this database like in this pseudocode with x = row count to insert and y = an arbitrary number of rows to limit the table to.
On inserting x number of rows:
{
if (total rows in table + x > y)
{
remove x number of rows form the start of the table (i.e. they have lowest id numbers)
}
insert the new rows at the end of the table
}
i.e. limiting the table to y number of rows max.
Many thanks!
I believe you should be able to achieve what you try using a trigger. How you do that would depend on the database you are using. You can have a look at the trigger page in wikipedia.