reading through your code …
if ( is_wp_error($change_ok) ) {
WriteErrorLog($change_ok->get_error_message());
}
is not applicable as $change_ok will always be true. ref https://codex.wordpress.org/Function_Reference/switch_to_blog
as the comments state it is better to use get_posts() and this may fix your issue, otherwise use $wpdb->prepare before your get_results.
also a comment is that your SQL statement will not work for the primary site..
$sql_posts = "select id, post_title, post_content from wp_".$blog_id."_posts where post_type="custom_add" and post_status="publish"";
A note is that the “wp_” table prefix can be changed in the wp-config.php file and if a site has done the “wp_” hardcoded prefix would never work the $wpdb->base_prefix
can be used to make the “wp_” always fit the current site.
also the wp_".$blog_id."_posts
is not going to work for the main site as the table structure is different
a simple function to get the current site WP database table prefix…
// Get the database prefix
function get_blog_prefix( $blog_id=null ) {
global $wpdb;
if ( null === $blog_id ) {
$blog_id = $wpdb->blogid;
}
$blog_id = (int) $blog_id;
if ( defined( 'MULTISITE' ) && ( 0 == $blog_id || 1 == $blog_id ) ) {
return $wpdb->base_prefix;
} else {
return $wpdb->base_prefix . $blog_id . '_';
}
}