用于更新插入

时间:2017-07-12 21:57:34

标签: sql-server stored-procedures insert-update

我正在处理一个应该在远程表中插入或更新行的存储过程。我尝试使用MERGE,但是当目标表是远程时,无法使用MERGE。

有人可以告诉我如何在sproc中进行更新?我是否需要先将记录读入临时表,然后比较这些值?我有兴趣更新的列值是FlagValue。

更新

我能够在另一台服务器上创建链接服务器并翻转目标和源。

我正在整理一个使用MERGE的存储过程,我想知道是否有人可以帮我查看代码并让我知道它是否正常。如果sku已经驻留在目标表中但是FlagValue值不同,则代码基本上必须更新FlagValue列,并且它必须插入也限制在USING()内的SELECT作为SOURCE的记录,而不是全部插入表产品中的记录。

更新的T-SQL:

ALTER PROCEDURE [dbo].[mn_RecordInfo_Upsert]
AS
BEGIN

    --Synchronize the target table with refreshed data from source table
    MERGE [dbo].[RecordInfo] AS [t]
    USING
        ( SELECT TOP 100 PERCENT
            [p].[ProductID]
          , [p].[Flag]
          FROM
            [server].[db].[dbo].[Product] [p]  -- Remote linked server table
          WHERE
            (
              [Category] = 2
              OR [Description] = 'This type of product' )
            AND LEN([ProductID]) = 10
            AND [ProductID] LIKE 'P0%'
          ORDER BY
            [Date] DESC
        ) AS [s]
    ON ( [t].[PID] = [s].[ProductID] ) 

    --When records are matched, update the records if there is any change
    WHEN MATCHED AND [t].[Flag] <> [s].[Flag]
        AND [t].[PID] = [s].[ProductID] THEN
        UPDATE SET
               [t].[Flag] = [s].[Flag]                          

    --When no records are matched, insert the incoming records from source table to target table
    WHEN NOT MATCHED BY TARGET THEN
        INSERT
               (
                 [PID]
               , [Flag] )
        VALUES (
                 [s].[ProductID]
               , [s].[Flag] )       

    --SELECT @@ROWCOUNT;
    OUTPUT
        $action AS [DMLAction]
      , [inserted].*
      , [deleted].*;
END;

感谢您的推荐。

1 个答案:

答案 0 :(得分:1)

如果我理解你的问题只是你所写的内容做了你的想法吗?我相信它确实如此。尽管再次加入import numpy as np import tensorflow as tf import glob import os tf_record_dir = os.getcwd() + '/' batch_size = 30 num_epochs = 100 filename = os.path.join(tf_record_dir, 'train.tfrecords') def _int64_feature(value): return tf.train.Feature(int64_list=tf.train.Int64List(value=[value])) def gen_tf_record_files(): print ('Writing', filename) writer = tf.python_io.TFRecordWriter(filename) for index in range(1000): example = tf.train.Example(features=tf.train.Features(feature={'image_id': _int64_feature(index) })) writer.write(example.SerializeToString()) writer.close() def inputs(): tfRec_files_list = glob.glob(filename) with tf.name_scope('input'): filename_queue = tf.train.string_input_producer(tfRec_files_list, num_epochs=num_epochs, name='string_input_producer') im_id = _read_and_decode(filename_queue) min_after_dequeue = 10 capacity = min_after_dequeue + 3 * batch_size im_ids = tf.train.shuffle_batch([im_id], batch_size=batch_size, num_threads=3, capacity=capacity, enqueue_many=False, min_after_dequeue=min_after_dequeue, name='batching_shuffling') return im_ids def _read_and_decode(filename_queue): # All of the bellow are symbolics reader = tf.TFRecordReader() _, serialized_example = reader.read(filename_queue) features = tf.parse_single_example(serialized_example, features={'image_id': tf.FixedLenFeature([], tf.int64) }) im_id = tf.to_int32(features['image_id'], name='ToInt32') return im_id def main(): # initialize graph gen_tf_record_files() g = tf.Graph() with g.as_default(): im_id = inputs() if tf.__version__.split('.')[0] == "1": init = tf.global_variables_initializer() else: init = tf.initialize_all_variables() #it is deprecated in TF 1.1 sess = tf.Session(config=tf.ConfigProto(log_device_placement=False)) with sess.as_default(): sess.run(init) # Start the queue runners. coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(sess=sess, coord=coord) im = sess.run(im_id) main() 是多余的,但您的更新看起来还不错。单个合并语句中的所有不同语句(例如target.sku = source.skuwhen matchedwhen not matched by source)将使用在顶部声明的连接条件,因此您不需要指定它再次。另一件需要考虑的事情是when not matched by target是否为空。如果是,请检查FlagValue之后target.FlagValue != source.FlagValue将返回错误。

至于你的插页,你是对的。它只会使用您定义的子查询的结果,并将其别名为null != null(旁注,虽然MSDN喜欢将它们设为别名sourcesource,但我倾向于targets因为他们不是保留关键字,并且在您输入时最终使用tsource作为实际关键字时避免混淆,因为例如,target。重点是,您可以随意为它们添加别名;您不仅限于这两个关键字。)

如果您想了解执行过程中发生的事情,您可以做两件事。第一种是在最后使用when not matched by target子句;像

这样简单的事情
OUTPUT

如果您发现... ( [SOURCE].[SKU], [SOURCE].[FlagValue] ) output $action as DMLAction, inserted.*, deleted.* 笨拙地工作,第二种方法是考虑将这些语句写成两个单独的语句而不是MERGE;一个MERGE和一个insert。在大多数情况下,update无论如何都会这样做,因此您不会失去性能,而且通常更容易选择MERGEinsert声明而不是我update的经验。

此外,在加入链接服务器时,我必须谨慎。有时它会表现得很好,但有时候它会完全自己做。如果远程表很大,您可能最终会扫描整个表并将其在链接服务器上进行管道传输,即使您不希望它获得任何接近本地表不良的计划的任何内容。