-- Take a mysqldump first; none of this is reversible.
UPDATE wp_options
SET option_value = 'http://shop.example.com'
WHERE option_name IN ('siteurl', 'home');
UPDATE wp_posts SET guid = REPLACE(guid, 'http://old.example.com', 'http://shop.example.com');
UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://old.example.com', 'http://shop.example.com');
-- wp_postmeta is left alone on purpose: replacing inside a serialised value
-- breaks its length prefix and the row stops unserialising.