Subject RE: [firebird-support] UPDATE sql with join like search
Author Svein Erling Tysvær
>I'm currently trying to create update sql for something like
>
>UPDATE TABLE1 T
>SET T.VALUE1 = NULL
>WHERE
> T.VALUE1 IN (SELECT A.VALUE1 FROM TABLE2 A WHERE VALUE2 = ?)

This can be very slow, Virgo, but I guess you already know that.

>But I'd like to do it so, that it uses indexes, like
>SELECT T.*
>FROM TABLE1 T JOIN TABLE2 A ON T.VALUE1 = A.VALUE1 WHERE A.VALUE2 = ?
>
>There are indexes on T.VALUE1 and A.VALUE2, so the plan is something like
>PLAN JOIN (A INDEX (TABLE2_$_VALUE2), T INDEX (TABLE1_$_VALUE1))
>
>Is it even possible without using stored procedure?

Depends on which Firebird version you use.

Try either:

EXECUTE BLOCK AS
DECLARE VARIABLE V1 INTEGER;
BEGIN
FOR SELECT DISTINCT VALUE1 FROM TABLE2 WHERE VALUE2 = <whatever> INTO :V1 DO
BEGIN
UPDATE TABLE1
SET VALUE1 = NULL
WHERE VALUE1 = :V1;
END
END

or

EXECUTE BLOCK AS
DECLARE VARIABLE V1 INTEGER;
BEGIN
FOR SELECT DISTINCT T.ID
FROM TABLE1 T
JOIN TABLE2 A ON T.VALUE1 = A.VALUE1
WHERE A.VALUE2 = <whatever> INTO :V1 DO
BEGIN
UPDATE TABLE1
SET VALUE1 = NULL
WHERE ID = :V1;
END
END

If you use an old version where EXECUTE BLOCK isn't available, you could try:

UPDATE TABLE1 T
SET T.VALUE1 = NULL
WHERE
EXISTS(SELECT * FROM TABLE2 A WHERE VALUE2 = ? AND T.VALUE1 = A.VALUE1)

The last alternative will still use NATURAL, but once upon a time Firebird didn't transform IN into EXISTS (that's why I stopped using IN <subselect> last century), so it could be considerably quicker than your alternative.

HTH,
Set