SQL Server简介

SQL Server是微软的一款关系型数据库。某些平台吹得天花烂坠,今天第一次在自己的项目中使用了下,感觉不是那么好,特别是SQL语句的支持度还是很欠缺,如limit等都不支持,还有特别单双引号都是需要特别注意的,下面是SQL Server的安装和使用总结:
SQL Server安装:
1.到官网下载下载器:https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads ,如图:
在这里插入图片描述
2.新建一个文件夹并将下载好的下载器移动到这个文件夹中(可以不新建,个人习惯将软件归类管理,但是后面会发现微软的软件很多你是无法很好的管理,因为它会不受控制的安装到C盘去,即使自定义了安装目录,但是还是有很多文件是装到C盘去,吐槽微软!),之后双击下载器后选中基本即可,如:
在这里插入图片描述
3.双击基本后会再次弹出一个许可协议,接受后将安装路径修改为自己新建的文件夹,之后点击安装继续,如:
在这里插入图片描述
4.看到下面界面表示数据库已经安装成功,此时可以继续安装SSMS(SSMS是一款数据库管理软件,类似SQLyog,但是没有SQLyog好用的数据库管理软件),如:
在这里插入图片描述
5.点击完SSMS后会跳到新的网页中去,此时点击如图所示位置即可下载可视化管理软件(如果需要中文,可以继续到下面Available languages点击chinese即可安装中文版),如:
在这里插入图片描述
6.将下载好的SSMS下载器放到重新新建的文件夹,之后双击,并修改安装路径后继续点击install进行下载安装,如:
在这里插入图片描述
7.安装完成后点击Close即可,点击完CLose后,此时桌面可能没有快捷方式,此时你可以到自己应用中找到名为:azuredatastudio.exe的程序之后双击即可,通过文件所在位置可以看到文件是安装在了C盘,我C盘坚决不安装与系统相关的软件,因此我会将整个文件剪切到其它盘,之后创建快捷方式,打开管理软件如下(类似编辑器,如果想要更可视化的管理数据库,那么还得继续选择其中的工具):
在这里插入图片描述
其中的工具如:
在这里插入图片描述
**node.js中使用SQL Server: **

node.js中使用SQL Server可以通过第三方包:mssql,类似node.js连接mysql的包mysql一样,我项目中涉及分库分表存储数据,下面我将我项目中主要代码粘贴如下可供参考:

配置默认数据库:默认数据库用来查询项目基础数据,文件命名为:mssqldefaultconfig.js

// 默认数据库配置:
// 引入前先: npm i mssql 下载依赖包
const mssql = require('mssql')
// 默认数据库配置:
const option = {// sql server数据库所在服务器:server: '***.**.***.***', // sql server数据库监听的端口号,默认1433:port: ****,// sql server数据库某个数据库名称:database: '********2021',// 用户名:user: '******',// 密码:password: '*********',options: {encrypt: false,  //加密enableArithAbort: false},pool: {min: 0,max: 10,idleTimeoutMillis: 3000}
}// 创建默认数据库连接池:
const pool = new mssql.ConnectionPool(option)
pool.on('error', err => {console.log('数据库连接错误: ', err)
})
// 连接数据库:
const connection = pool.connect()// 封装一个执行sql语句的方法,用来操作数据库:
const defaultDataBaseQuery = async (sql, callBack) => {  const ps = new mssql.PreparedStatement(await connection)ps.prepare(sql, err => {  if (err){  console.log('prepare错误:' + err)return}  ps.execute('', (err, result) => {  if (err){  console.log('execute错误:' + err)return}  ps.unprepare(err => {  if (err){  console.log('unprepare错误:' + err)callBack(err, null)return}  callBack(err, result)})})})
}// 导出默认数据库:
module.exports = defaultDataBaseQuery

配置动态数据库 :动态数据库是指按规定的日期自动切换到某个数据,文件命名为:mssqlswitchconfig.js

// 动态库配置:
const mssql = require('mssql')
// 定时事务:一个第三方的包,类似定时器,可以设置某段代码多久执行一次(某个日期点执行某段代码)
const schedule = require('node-schedule')
// 引入默认数据库配置:动态库切换也是需要借助基础库的,因此需要引入基础库:
const defaultDataBaseQuery = require('./mssqldefaultconfig')// 导出一个动态的数据库配置:按年份配置数据库
function createSqlServeOption() {let date = new Date()let yearstr = date.getFullYear()// 动态数据库配置:let optionObj = {server: '***.**.***.***', port: ****,// 动态库命名最方便的就是前缀固定+后缀年份等database: '******' + yearstr,user: '*****',password: '************',options: {encrypt: false,  //加密enableArithAbort: false},pool: {min: 0,max: 10,idleTimeoutMillis: 3000}}return optionObj
}// 程序启动配置当前年份动态库option:
let option = createSqlServeOption()
// 数据库连接变量
let pool;// 程序启动连接当前年份动态库:
pool = new mssql.ConnectionPool(option)// 每年1月1日自动切换到最新数据库:
schedule.scheduleJob('0 0 0 1 1 *', function () {const date = new Date()const yearstr = date.getFullYear()let dbStr = '******' + yearstr// 降低频率切换:因为此项目为老项目二开,数据库中数据和数据结构都是不动的,只提供使用权,这里动态创建新的数据库业务不在我项目,所以我无法创建数据库且不确定新的数据库是否已经创建好,因此只能不断的查询新的数据库是否存在,如果存在立马切换到新的数据库,否则持续每次降低频率的尝试查询数据库是否存在let count = 0// 如果新的一年数据库创建了那么立马切换到新创建的数据库,否则延迟递归切换function switchDB () {// SQL Server中无法使用:'SELECT table_name FROM `INFORMATION_SCHEMA`.`TABLES` WHERE table_schema = ******'+yearstr此sql语句查询某个数据库中是否有某表,只能通过下面数据查询到所有数据库,然后去判断数据库中是否有新的数据库名称let sql = 'select * From master.dbo.sysdatabases'defaultDataBaseQuery(sql,async (error,result) => {try {if (error) {throw error} else {const isExist = result.recordset.find(item => item.name == dbStr) // 不存在是返回undefinedif (isExist) {option.database = dbStr// 动态切换新的数据库连接:如果将new mssql.ConnectionPool(option)提到最外面,这里我不能保证它会重新创建新连接,为了确保期间,我在这里重新创建一次pool = new mssql.ConnectionPool(option)// 存在的情况下return掉,否则继续延迟尝试切换:return} else {// 延迟重新判断是否存在数据库setTimeout(() => {count++switchDB()},1000 * count)}}} catch (err) {console.log('查询新创建数据库是否存在失败' + err)}})}switchDB()
})// 连接池创建错误时:
pool.on('error', err => {console.log('数据库连接错误: ', err)
})// 创建数据库连接:
const connection = pool.connect()// 动态库查询方法:
const switchDataBaseQuery = async (sql, callBack) => {  const ps = new mssql.PreparedStatement(await connection)ps.prepare(sql, err => {  if (err){  console.log('prepare错误:' + err)return}  ps.execute('', (err, result) => {  if (err){  console.log('execute错误:' + err)return}  ps.unprepare(err => {  if (err){  console.log('unprepare错误:' + err)callBack(err, null)return}  callBack(err, result)})})})
}// 导出动态数据库:
module.exports = switchDataBaseQuery 

查询页api接口路由文件

// 记录查询页:// 引入日期格式化函数:
const {dataFormat} = require('../utils/utils')
// 引入路由模块:
const Router = require('koa-router')
// 引入默认数据库配置
const defaultDataBaseQuery = require('../config/mssqldefaultconfig')
// 引入动态数据库配置
const switchDataBaseQuery = require('../config/mssqlswitchconfig')
// 引入redis配置文件:
const redisClient = require('../config/redisconfig')
// 创建路由实例:
const router = new Router({prefix:'/api'})//里面可接收一个对象,可以设置些默认配置,如{prefix:'/api'}设置路由匹配前缀// 在创建路由时默认加了前缀 /api ,下面router.post('/login', ()=>{})可直接匹配:'/api/login'路由// 查实时值接口:
router.post('/getrealtime',async (ctx, next) => {let {id, ParaId} = ctx.request.body// 设备单位等参数redis缓存keylet keys = 'equipmentunit' + ParaIdreturn new Promise((resolve,reject) => {// 查仪表相关配置参数:function queryEquipOption() {// 判断是否存在key:存在走缓存,否则走数据库:return new Promise((resolve,reject) => {redisClient.exists(keys, (err, res) => {if (res == 0) {let sql1 = 'SELECT Name,Unit,Xh FROM Equipment_Para_Two WHERE FId= '+ParaId +' AND WeiXin=1'defaultDataBaseQuery(sql1, (error, result) => {if (error) {ctx.body = {cod: 201, msg: '查询错误!'}console.log('查询实时值sql1错误:' + error)reject()} else {if (result.recordset.length === 0) {ctx.body = {cod: 200, msg: '无实时值!', resultList: [], time: dataFormat()}resolve()return}// 将查询到的数据存到redis中600秒过期:redisClient.setex(keys, 60 * 10, JSON.stringify(result))resolve(result)}})} else {redisClient.get(keys, (error,res) => {resolve(JSON.parse(res))})}})})}// 查实时值数据:async function queryTimeData() {const option = await queryEquipOption()// 要获取的通道const dnArray = [...new Set(option.recordset.map(it => 'D' + it.Xh))]// 要查询的通道值字段:const dnStr = dnArray.toString()// 查询时刻值:let sql2 = 'SELECT TOP 1 '+dnStr+', SubTime FROM Equipment_Data WHERE EqId = '+id+' order by id desc'switchDataBaseQuery(sql2, (error, result) => {if (error) {ctx.body = {cod: 201, msg: '查询错误!'}console.log('查询实时值sql2错误:' + error)} else {if (result.recordset.length === 0) {ctx.body = {cod: 200, msg: '无实时值!', resultList: [], time: dataFormat()}resolve()return}// 实时值数组let resultArray = []option.recordset.forEach(item => {resultArray.push({...item,...{value: result.recordset[0]['D' + item['Xh']]}})})ctx.body = {cod: 200, msg: '请求实时值数据成功!', resultList: resultArray, time: dataFormat(result.recordset[0].SubTime)}resolve()}})}queryTimeData()})
})// 查历史值接口:
router.post('/gethistory', async (ctx, next) => {const {date1, date2, ParaId, id, page} = ctx.request.bodyconst startYear = date1.slice(0,4)const endYear = date2.slice(0,4)if (startYear !== endYear) {ctx.body = {cod: 200, msg: '日期不能跨年!', resultList: []}return}// 设备单位等参数redis缓存keylet keys = 'equipmentunit' + ParaIdreturn new Promise((resolve, reject) => {// 查仪表相关配置参数:function queryEquipOption() {// 判断是否存在key:存在走缓存,否则走数据库:return new Promise((resolve,reject) => {redisClient.exists(keys, (err, res) => {if (res == 0) {let sql1 = 'SELECT Name,Unit,Xh FROM Equipment_Para_Two WHERE FId= '+ParaId +' AND WeiXin=1'defaultDataBaseQuery(sql1, (error, result) => {if (error) {ctx.body = {cod: 201, msg: '查询错误!'}console.log('查询实时值sql1错误:' + error)reject()} else {if (result.recordset.length === 0) {ctx.body = {cod: 200, msg: '无实时值!', resultList: []}resolve()return}// 将查询到的数据存到redis中600秒过期:redisClient.setex(keys, 60 * 10, JSON.stringify(result))resolve(result)}})} else {redisClient.get(keys, (error,res) => {resolve(JSON.parse(res))})}})})}// 查历史值数据:async function queryHistoryData() {const option = await queryEquipOption()// 要获取的通道const dnArray = [...new Set(option.recordset.map(it => 'D' + it.Xh))]// 要查询的通道值字段:const dnStr = dnArray.toString()if (page < 1) {ctx.body = {cod: 200, msg: '页数无效!', resultList: []}return}let skip = (page - 1)*10// 查询历史值:const date = new Date()const currentYear = date.getFullYear()let sql2;// 如果查询日期是当前年份,则执行当前年份动态库,否则切换到对应的历史数据库查询数据:if (startYear == currentYear) {sql2 = "select top 10 "+dnStr+" ,SubTime,EqId from (select row_number() over(order by id desc) as rownumber, "+dnStr+" ,SubTime,EqId from Equipment_Data) temp_row where EqId = "+id+" and SubTime between '"+date1+"' and '"+date2+"' and rownumber > " +skip} else {sql2 = "select top 10 "+dnStr+" ,SubTime,EqId from (select row_number() over(order by id desc) as rownumber, "+dnStr+" ,SubTime,EqId from [YLinK"+startYear+"].[dbo].[Equipment_Data]) temp_row where EqId = "+id+" and SubTime between '"+date1+"' and '"+date2+"' and rownumber > " +skip}switchDataBaseQuery(sql2, (error, result) => {if (error) {ctx.body = {cod: 201, msg: '查询错误!'}console.log('查询历史值sql2错误:' + error)} else {if (result.recordset.length === 0) {ctx.body = {cod: 200, msg: '无历史值!', resultList: []}resolve()return}// 历史值数组let resultArray = []// 遍历历史值result.recordset.forEach(item => {// 二维数组子数组:let arr = []// 遍历单位数组:option.recordset.forEach(uitem => {// 遍历历史值对象:for (key in item) {if (key.slice(1,2) == uitem.Xh) {arr.push({...uitem,value:item[key]})}}})resultArray.push({time: dataFormat(item.SubTime), ValueArray: arr})})ctx.body = {cod: 200, msg: '请求历史值数据成功!', resultList: resultArray}resolve()}})}queryHistoryData()})
})// 查充值记录接口
router.post('/getpayrec', async (ctx, next) => {const {date1, date2, id, page} = ctx.request.bodyreturn new Promise((resolve,reject) => {// 查询充值记录:if (page < 1) {ctx.body = {cod: 200, msg: '页数无效!', resultList: []}resolve()return}let skip = (page - 1) * 10let sql = "select top 10 EquipmentId,SbTime,No,Amount from (select row_number() over(order by id desc) as rownumber,EquipmentId,SbTime,No,Amount from PayRec) temp_row where EquipmentId = "+id+" and SbTime between '"+date1+"' and '"+date2+"' and rownumber > " +skipdefaultDataBaseQuery(sql, (error, result) => {if (error) {ctx.body = {cod: 201, msg: '查询错误!'}console.log('查充值记录sql错误:' + error)} else {result.recordset.map(item => {item.SbTime = dataFormat(item.SbTime)})ctx.body = {cod: 200, msg: '请求充值记录数据成功!', resultList: result.recordset}resolve()}})})
})// 退款记录接口
router.post('/getrefund', async (ctx, next) => {const {date1, date2, id, page} = ctx.request.bodyreturn new Promise((resolve,reject) => {// 查询退款记录:if (page < 1) {ctx.body = {cod: 200, msg: '页数无效!', resultList: []}resolve()return}let skip = (page - 1) * 10let sql = "select top 10 EquipmentId,SbTime,No,Amount from (select row_number() over(order by id desc) as rownumber,EquipmentId,SbTime,No,Amount from Refund) temp_row where EquipmentId = "+id+" and SbTime between '"+date1+"' and '"+date2+"' and rownumber > " +skipdefaultDataBaseQuery(sql, (error, result) => {if (error) {ctx.body = {cod: 201, msg: '查询错误!'}console.log('查退款记录sql错误:' + error)} else {result.recordset.map(item => {item.SbTime = dataFormat(item.SbTime)})ctx.body = {cod: 200, msg: '请求退款记录数据成功!', resultList: result.recordset}resolve()}})})
})// 导出路由
module.exports = router

index启动文件

// 引入设置响应头的中间件:
const setResponseHeader = require('./middelware/setresponseheader')
// 引入解析请求体的中间件:koa-bodyparser
const bodyParser = require('koa-bodyparser')
// 导入查询页路由文件
const recordqueryserve = require('./serves/recordqueryserve')const Koa = require('koa')
// 创建Koa实例对象:
const app = new Koa()// 挂载设置响应头的中间件:
app.use(setResponseHeader)
// 挂载koa-bodyparser中间件:如果不配置的话在路由页就不能通过ctx.request.body拿到请求体
app.use(bodyParser())// 挂载查询页接口路由:
app.use(recordqueryserve.routes())// 绑定端口号:
app.listen(3000,() => {console.log('serve is running at 3000!')
})

提示:本文图片等素材来源于网络,若有侵权,请发邮件至邮箱:810665436@qq.com联系笔者 删除。

笔者:苦海

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/575082.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows下断言的类型及实现

一、内容综述 本文主要介绍Windows下断言assert的实现&#xff0c;并总结断言的不同应用准则。最后给出一个windows自定义断言的方法。 本文行文参考《Debugging Windows Programs》第三章相关内容&#xff0c;如果有兴趣的话建议读者可以深入阅读下。 二、断言的类型 1. ANSI…

linux右上角不显示网络连接_来体验下Linux吧

在前面的几期中我们从树莓派开始了解Linux&#xff0c;大家可能已经想来试一下手了。趁热打铁&#xff0c;本期我将介绍两种方便体验学习Linux的方法&#xff0c;在线体验或者安装虚拟机。1 在线体验Linux如果想快速的体验下Linux系统&#xff0c;我们可以选择云计算服务商提供…

python md5解密_python 生成文件MD5码

pymd5.py的代码如下&#xff1a; #-*-coding:utf-8-*-Created on 2012-5-25 author: kanpiaoxueimport hashlib import os import sys def printUsage(): print (Usage: [python] pymd5.py ) def createMD5(filePath): if not os.path.isfile(filePath): printUsage() else: tm…

Java数据结构、list集合、ArrayList集合、LinkedList集合、Vector集合

数据结构&#xff1a; 数据存储的常用结构有&#xff1a;栈、队列、数组、链表、红黑树。 栈&#xff1a;stack,又称堆栈&#xff0c;它是运算受限的线性表&#xff0c;其限制是仅允许在标的一端进行插入和删除操作&#xff0c;不允许在其他任何位置进行添加、查找、删除等操…

第11章 GUI Page436 使用缓冲DC, wxBufferedPaintDC

所谓“缓冲DC”&#xff0c;是指将所有图元都先划到一个人眼看不到的“设备上下文”之上&#xff0c;最后再一次性复制到真正的屏幕DC之上&#xff0c;这样我们就看不到中间画的过程了&#xff0c;也就不会感到闪烁了。 注意&#xff0c;这时不能解除ScrolledWindow1的背景擦除…

Tomcat+JSP经典配置实例

经常看到jsp的初学者问tomcat下如何配置jsp、servlet和bean的问题&#xff0c;于是总结了一下如何tomcat下配置jsp、servlet和ben&#xff0c;希望对那些初学者有所帮助。    一、开发环境配置    第一步&#xff1a;下载j2sdk和tomcat&#xff1a;到sun官方站&#xf…

python海龟编辑器画小汽车_【海龟编辑器下载】海龟编辑器(Python编辑器) v1.3.4 官方免费版-趣致软件园...

海龟编辑器是一款专为广大少儿打造的Python编辑器&#xff0c;该软件功能强大且使用便利&#xff0c;可以帮助孩子们以搭积木的方式来学习Python&#xff0c;并且支持Python代码和图形化积木的双向互相转译&#xff0c;不但可以有效提升孩子的学习兴趣&#xff0c;而且还能够降…

微信小程序中组件的使用

微信小程序中组件的使用&#xff1a; 微信小程序中组件定义在项目根目录下components文件夹下&#xff0c;在页面使用的时候需要在页面的json文件中声明&#xff0c;如 父组件向子组件传值及子组件向父组件传值&#xff1a; 父组件wxml中&#xff1a;通过属性绑定值的方式向…

如何保证交叉表编译器和目标系统版本一致_嵌入式系统词汇表

欢迎FPGA工程师加入官方微信技术群点击蓝字关注我们FPGA之家-中国最好最大的FPGA纯工程师社群AASIC(专用集成电路) Application-Specific Integrated Circuit. A piece of custom-designed hardware in a chip. 专用集成电路。一个在一个芯片上定制设计的硬件。address bus (地…

动态定义数组

首先&#xff1a;为什么需要动态定义数组呢&#xff1f; 这是因为&#xff0c;很多情况下&#xff0c;在预编译过程阶段&#xff0c;数组的长度是不能预先知道的&#xff0c;必须在程序运行时动态的给出 但是问题是&#xff0c;c要求定义数组时&#xff0c;必须明确给定数组的…

sql随机抽取数据50条_厉害!苏宁通过citus打造分布式数据库抗住DB高负载

2018-07-16 23:59内容来源&#xff1a;2017 年 10 月 20 日&#xff0c;苏宁云商IT总部资深技术经理陈华军在“PostgreSQL 2017中国技术大会”进行《苏宁citus分布式数据库应用实践》演讲分享。IT 大咖说&#xff08;微信id&#xff1a;itdakashuo&#xff09;作为独家视频合作…

java中Debug调试、异常的概念、异常体系、处理异常的关键字try/catch/finally/throw/throws、多个异常使用捕获并处理的方式、继承关系中处理异常、自定义异常类

Debug调试&#xff1a; bug指程序当中遇到的一些错误异常&#xff0c;Debug指调试bug,找到bug对其解决&#xff1b;debug可以让代码逐行执行&#xff0c;查看代码执行的过程&#xff0c;调试程序中出现的bug或异常。 public class DebugClass {public static void main(Strin…

densenet网络结构_FC-DENSENET用于图像分割学习笔记

近日使用FC Dense Net 做分割&#xff0c;记录学习使用过程。FC-DenseNet 原文链接&#xff1a;https://arxiv.org/abs/1611.09326 《The One Hundred Layers Tiramisu: Fully Convolutional DenseNets for Semantic Segmentation》初次使用此网络&#xff0c;第一眼是被这个名…

mongodb mysql资源占用_如何限制mongodb启动时占用过多内存

默认情况下&#xff0c;mongodb占用的内存大小为&#xff1a;Starting in 3.4, the WiredTiger internal cache, by default, will use the larger of either:50% of RAM minus 1 GB, or256 MB.下面我们来看一下限制mongodb启动时占用内存的方法&#xff1a;新增配置文件 /etc/…

js ...运算符_「 giao-js 」用js写一个js解释器

前言在这篇文章中,我们将通过 JS 构建我们自己的 JS 解释器,用 JS 写 JS,这听起来很奇怪,尽管如此,这样做我们将更熟悉 JS,也可以学习 JS 引擎是如何工作的!什么是解释器 (Interpreter) ?解释器是在运行时运行的语言求值器,它动态地执行程序的源代码。 解释器解析源代码,从源代…

地区json文件_【小例子】使用jQuery实现省市区三级联动显示,附源码json文件

开发工具-intellij IDEA需求1.实现对json文件的读取。2.可以在省级选择所有省名和直辖市名3.选择一级省名后自动刷新市名4.选择二级市名后自动刷新区名逻辑分析第一步&#xff1a;读取json文件第二步&#xff1a;遍历出所有一级的省名第三步&#xff1a;把遍历出来的省名动态追…

qt 状态栏

有段时间没有写过博客了。假期去上海旅游&#xff0c;所以一直没有能够上网。现在又来到这里&#xff0c;开始新的篇章吧&#xff01;今天的内容主要还是继续完善前面的那个程序。我们要为我们的程序加上一个状态栏。状态栏位于主窗口的最下方&#xff0c;提供一个显示工具提示…

动态获取textarea后面的p标签_HTML简单标签连起实现的小玩意:

《今天不发知识点&#xff0c;刚被误封了&#xff0c;所有没有太多时间去给整理哈&#xff0c;请谅解》&#xff08;谢谢欣赏&#xff09;前面发了那么多HTML标签&#xff0c;今天来玩个小视频&#xff0c;小白也能几分钟就会的&#xff0c;代码没有写好&#xff0c;时间急了点…

elipse+pydev+python开发arcgis脚本程序

环境配置参考&#xff1a;http://www.cnblogs.com/halfacre/archive/2012/07/22/2603848.html 添加arcpy类库、arctoolbox、arcgis-bin如下所示。 windos——preference——pydev 完成环境配置。 二、获取文件路径Python方法 os.getcwd()返回的是当前文件的目录。假如我的代码…

BZOJ3427 Poi2013 Bytecomputer

可以YY一下嘛 最后一定是-1, -1, ..., -1, 0, 0, ... 0, 1, 1, ..., 1的一个数列 于是f[i][j]表示到了第i个数&#xff0c;新数列的第j项为-1 or 0 or 1的的最小代价 然后就没有然后了 1 /**************************************************************2 Problem: 3427…