首页
高清壁纸
统计
留言
推荐
Json工具
Search
1
通过iframe嵌套时,被302重定向怎么办?
2,431 阅读
2
关于 MySQL Binlog 权限
1,132 阅读
3
Windows安装PECL
1,045 阅读
4
JS常用监听事件【监听键盘、触控、鼠标、多媒体、打印、剪贴板、表单等事件】
1,026 阅读
5
json在线转换Swagger/OpenAPI文档的注释文本格式
792 阅读
抽奖系统
tony爱编程
收藏分享
经验总结
其它杂类
常用工具
登录
Search
标签搜索
抽奖系统
html+JS
抽奖HTA
js
MySQL
HTA版
源码
hta属性
ecshop
Meta
拖动
javascript
MySQL函数
git提交慢
提交卡
laravel-admin
FSO
redis
文件操作
mysql备份
Tony哥
累计撰写
55
篇文章
累计收到
11
条评论
首页
栏目
抽奖系统
tony爱编程
收藏分享
经验总结
其它杂类
常用工具
页面
高清壁纸
统计
留言
推荐
Json工具
搜索到
26
篇与
的结果
2024-07-19
go文字生成图片的较靠谱的方法
我们经常会遇到一些情况,在转换昵称做图片海报的时候,出现字体库内资源不够导致字体无法转化的清理,搜遍全网也没有一个很好的解决办法,于是就自动动手封装了一个,原理还是逃脱不掉字体库,于是我封装了一些常用的字体库(且支持中日韩和一些常用的符号图形)使用说明引入扩展 go get gitee.com/archn/act-red-go加载依赖 go mod tidy导入方法 import "gitee.com/archn/act-red-go/text-to-img/toimage"使用方法:toimage.RenderTextToPNG(text string, fontPaths []string, outputOrFile any, args ...TextToPngArgs) error文字转换为图片方法,用于常规海报生成等fontPaths 默认使用内置字体 如果要新增请注意 排序靠前的优先匹配outputOrFile 可以是文件名称路径(绝对路径请已/开头)、也可以是文件句柄os.File用于内容写入args 为可选参数,用于配置文字的颜色大小图片大小等基本信息详情请关注对应结构体,(默认12px|黑色|自适应)toimage.ConvertRemoteImageToPNG(imageURL string, output *os.File) error任意图片转png方法使用例子package main import "gitee.com/archn/act-red-go/text-to-img/toimage" func main() { err := toimage.RenderTextToPNG("新ღღ你不认识吗?A中国🐂나사랑해요12abα🌸double 🇨🇳 🧧ৡღ ℒℴѵℯ依·訫ꦿ⸙ ঞ 不留遗憾 ོꦿ ࿐ ₅₂ₒ ꧁哥 ໊是ꕥ电ꦿ工꧂", nil, "abc.png", toimage.TextToPngArgs{Size: 30}) if err != nil { return } } 包共享地址act-red-go 如有需要请自行扩展或提供宝贵建议
2024年07月19日
65 阅读
0 评论
0 点赞
2023-10-20
go进程独占文件的实现,可用于单进程锁等其它逻辑
在网上搜了一大圈,找到了一个独占文件的逻辑用了下,发出来和大家分享一下,写的还是不错的,我试了其它的一些方法,比如说 _, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY, os.ModeExclusive) 这些乱起八糟的说明还是不能行,结果这套代码可以,那么就分享一下吧!好吧直接上代码package main import ( "flag" "fmt" "os" "syscall" "time" ) var filename string var openSec int64 func main() { flag.Int64Var(&openSec, "openSec", 60, "独占的秒数") flag.StringVar(&filename, "filename", "D:/dd.txt", "需要独占打开得文件") flag.Parse() lockFile(filename, openSec) } func lockFile(filename string, openSec int64) error { _, err := os.Stat(filename) if err != nil { return fmt.Errorf("打开文件[%s]失败,%v", filename, err) } p, err := syscall.UTF16PtrFromString(filename) if err != nil { return err } fd, err := syscall.CreateFile(p, syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, nil, syscall.OPEN_EXISTING, // syscall.CREATE_ALWAYS syscall.FILE_ATTRIBUTE_NORMAL, 0, ) if err != nil { return err } time.Sleep(time.Second * time.Duration(openSec)) syscall.Close(fd) return nil }以上代码是别的写的,那么我拿他来做了个函数封装,用于我的程序单进程锁其实下面这些封装是不够完美的,相当于跑了一个独立线程来锁死文件,由于go还是不怎么熟练先凑合用了,如果你有更合适的方案欢迎发过来一起学习一下func main() { executablePath, _ := os.Executable() path = filepath.Dir(executablePath) if !lockProcess() { s := "仅能执行一个进程" writeToLogFile(s) fmt.Println(s) return } // 业务逻辑... } // 判断是否与其它实例并行 func lockProcess() bool { filePath := filepath.Join(path, ".lock") file, err := os.OpenFile(filePath, os.O_CREATE, 0666) if err != nil { return false } file.Close() go func() { err := lockFile(filePath) if err != nil { return } for { time.Sleep(time.Hour * 1000) } }() return true } func lockFile(filename string) error { _, err := os.Stat(filename) if err != nil { return fmt.Errorf("打开文件[%s]失败,%v", filename, err) } p, err := syscall.UTF16PtrFromString(filename) if err != nil { return err } _, err = syscall.CreateFile(p, syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, nil, syscall.OPEN_EXISTING, // syscall.CREATE_ALWAYS syscall.FILE_ATTRIBUTE_NORMAL, 0, ) if err != nil { return err } return nil }
2023年10月20日
345 阅读
1 评论
0 点赞
2023-08-22
go实现的SSE长连接封装
此方法自己尝试过可以借鉴参考,升级改造请自便package sse import ( "fmt" "github.com/gin-gonic/gin" "net/http" "time" ) // - SSE 相关封装 ----------------------- /* 输出说明: 1. Data等于空 不输出 2. Data+Event与上一个输出一致 不重复输出 3. 业务逻辑报错会向前端发出发送一个close事件 需要前端收到后主动close()请求 前端示例: const es = new EventSource(url+'auth-token='+token), listener = function (event) { console.log(event); var div = document.createElement("div");var type = event.type; div.appendChild(document.createTextNode(type + ": " + (type === "message" ? event.data : es.url)));document.body.appendChild(div); }; es.addEventListener("open", listener); es.addEventListener("message", listener); es.addEventListener("error", listener); es.addEventListener("close", function(ret){ es.close(); listener(ret) }); */ // MessageEvent 定义 SSE 事件 type MessageEvent struct { Id string Event string // Data+Event与前一个输出一致 不输出 Data string // Data等于空 不输出 } // 实现 SSE 事件的 String() 方法 func (e MessageEvent) String() string { s := "" if e.Id != "" { s += "id:" + e.Id + "\n" } if e.Event != "" { s += "event:" + e.Event + "\n" } s += fmt.Sprintf("data:%s\n\n", e.Data) return s } // SseOut see协议输出 // // fun(i 循环计数器)(事件结构体,下一个循环延迟时间) 该函数执行业务逻辑并将结果写入通道 func SseOut(c *gin.Context, T func(i int64) (MessageEvent, time.Duration, error)) { defer func(){}() messageChan := make(chan MessageEvent, 5) c.Header("Content-Type", "text/event-stream") c.Header("Cache-Control", "no-cache") c.Header("Connection", "keep-alive") w := c.Writer w.WriteHeader(http.StatusOK) flusher, _ := w.(http.Flusher) temp := "" //结果比对临时变量 var Err error // 监听客户端信号 closeNotify := c.Request.Context().Done() go func() { defer func() { if err := recover(); err != nil { // 捕获到 panic return } }() <-closeNotify close(messageChan) return }() // 执行业务逻辑 go func() { defer func() { if Err != nil { close(messageChan) return } if err := recover(); err != nil { // 捕获到 panic return } }() // 通道活性探测利用业务空闲时间独立执行 i := int64(0) for { e, t, err := T(i) if err != nil { Err = err break } //--两次结果一致的数据阻止输出 if temp != e.Data+e.Event { temp = e.Data + e.Event } else { e.Data = "" } if e.Data != "" { i++ messageChan <- e } else { messageChan <- MessageEvent{ Event: "__ping__", } } if t != 0 { time.Sleep(t) } } }() // SSE 监听并输出 for { if message, ok := <-messageChan; ok && Err == nil { if message.Event == "__ping__" { continue } fmt.Fprintf(w, "%s", &message) flusher.Flush() } else { if Err != nil { // 向客户端发送 SSE 事件 fmt.Fprintf(w, "%s", &MessageEvent{ Id: "-500", Event: "close", Data: Err.Error(), }) // 刷新 response buffer flusher.Flush() } break } } } 引用其它业务逻辑自行根据业务需求写入.... sse.SseOut(c, func(index int64) (Row sse.MessageEvent, Sleep time.Duration, Err error) { // 下一轮循环延迟时间 Sleep = time.Second * 3 // 数据 Row.Data = "" Row.Id = fmt.Sprintf("%d", index) Row.Event = action //--登录状态事件 if index > 0 { return } return }) ....
2023年08月22日
402 阅读
0 评论
0 点赞
2023-02-01
js计算字符串的hash值getHashCode
在网上搜集到的一个很实用的js版本的类hahs算法,无论多少字符串,计算其为唯一的id的取值用非常实用,分享给大家 /** * 计算字符串的hash值 * @param {string} str 字符串 * @param {boolean} caseSensitive [可选]忽略大小写 * @returns */ const getHashCode = function (str,caseSensitive) { str = str.toString(); if(!caseSensitive){ str = str.toLowerCase(); } var hash = 1315423911, i, ch; for (i = str.length - 1; i >= 0; i--) { ch = str.charCodeAt(i); hash ^= ((hash << 5) + ch + (hash >> 2)); } return (hash & 0x7FFFFFFF); }
2023年02月01日
372 阅读
0 评论
0 点赞
2023-01-12
JS实现Web应用或网站发送浏览器Notification通知
在开发一个Web应用系统或者一个网站时,当用户触发了某个事件,或者系统想通知用户某个事件,比如有一条新的消息、其他人点赞或者评论了文章、系统流程被审核通过了等等诸如此类的场景,通常可能会想到 应用内通知 的方式,但是这种方式有一个局限,就是如果用户切换到浏览器其他页签或者其他应用程序时,可能无法及时看到应用系统的通知,那么这个时候就可以借助于浏览器的 Notification 通知功能了。1、什么是浏览器的 Notification ?Notification 是浏览器提供的一种允许网页向用户显示系统通知的机制,这种系统通知是在顶级浏览上下文视口之外,因此即使用户已经切换标签页或移动到不同的应用程序,也可以显示,并且 Notification 相关的 API 被设计成与不同平台上的现有通知系统兼容。首先来看看浏览器的 Notification 通知是什么样的,这里以 SegmentFault 网站为例,只要有新用户关注或者文章被点赞收藏,SegmentFault 网站都会自动发送 Notification 通知(能看到通知的前提是要允许网站发送通知),具体通知如下:除了 SegmentFault 网站外,还可以看看网页版微信的系统通知,也是类似的。2、如何使用 Notification ?要显示一个系统通知,一般需要分成两步:用户授予显示通知的权限、发送系统通知。(1)用户授予显示通知的权限系统要给用户发送通知,如果用户不想查看这个通知,即没有授予相应的权限,那么即使通知发出了,用户也是无法看到的。如何向用户询问是否允许查看系统通知的权限呢?可以使用下面的方法Notification.requestPermission()该方法的返回值有三个:granted、denied、default,最新的规范已将此方法更新为基于 promise 的语法,工作原理如下:Notification.requestPermission().then(function(permission) { ... });下面来看一个具体的实例,在 localhost 上询问显示系统通知的权限,根据不同的选择结果,打印相应的日志信息,代码如下:Notification.requestPermission().then(function(result) { if (result === 'denied') { console.log('拒绝显示系统通知'); return; } if (result === 'default') { console.log('默认'); return; } console.log('允许显示系统通知') });按下F12,打开 Chrome 的控制台,复制上面的代码运行后,可以看到浏览器会弹出一个询问框,如下:不同的选择,控制台会输出不同的结果允许:控制台会输出 允许显示系统通知,如果选择了允许,再次请求权限时,不会再弹出选择框,而是在控制台直接输出允许显示系统通知;禁止:控制台会输出 拒绝显示系统通知,如果选择了拒绝,再次请求权限时,不会再弹出选择框,而是在控制台直接输出拒绝显示系统通知;;x关闭:控制台会输出 默认,如果直接关闭了,再次请求权限时,依然会弹出选择框;选择【允许】后,此时再点击地址栏的信息按钮,可以看到通知已开启了,如下:如果不想显示通知了,可以直接在此处关闭通知即可,也可以使用下面的语句来查看当前用户的授权情况,如下:Notification.permission运行后,输出结果'granted'(2)发送系统通知当用户允许显示系统通知后,就可以发送通知了,这时可以使用 Notification() 构造函数创建一个新通知,这个方法可以传入两个参数,具体如下:title(必传)定义一个通知的标题,当它被触发时,它将显示在通知窗口的顶部。options(可选)options 对象包含应用于通知的任何自定义设置选项,常用的选项有:dir : 文字的方向;它的值可以是 auto(自动), ltr(从左到右), or rtl(从右到左);lang: 指定通知中所使用的语言。这个字符串必须在 BCP 47 language tag 文档中是有效的;body: 通知中额外显示的字符串;tag: 赋予通知一个 ID,以便在必要的时候对通知进行刷新、替换或移除;icon: 一个图片的 URL,将被用于显示通知的图标;除了上述5个常用选项外,还有其他的 badge、image、data、vibrate、renotify、requireInteraction 等,具体可查看官方网站的介绍 https://developer.mozilla.org/zh-CN/docs/Web/API/notification/Notification下面来测试一个简单的通知,代码如下:let notification = new Notification('有一条新通知');这个通知只有标题,运行后,可以看到增加一些 options 选项,再次来测试一下系统通知,修改后的代码如下:let notification = new Notification('有一条新通知', { dir: 'ltr', lang: 'zh-CN', body: '通知的正文内容:你的请假流程已批准', icon: 'http://localhost/coder/favicon.ico' });运行后,可以看到通知如下 (3)通知事件Notification 通知有四种事件,可以通过监听通知事件来执行不同的操作,具体事件如下:Notification.onclick:对 click 事件的处理,每当用户点击通知时被触发;Notification.onshow:对 show 事件的处理,当通知显示的时候被触发;Notification.onerror:对 error 事件的处理,每当通知遇到错误时被触发;Notification.onclose:对 close 事件的处理,当用户关闭通知时被触发。下面来测试一下通知事件的监听,代码如下:let notification = new Notification('有一条新通知', { dir: 'ltr', lang: 'zh-CN', body: '通知的正文内容:你的请假流程已批准', icon: 'http://localhost/coder/favicon.ico' }); // 监听通知显示事件 notification.onshow = () => console.log('通知已显示'); // 监听通知点击事件 notification.onclick = () => console.log('通知被点击'); // 监听通知被关闭事件 notification.onclose = () => console.log('通知被关闭'); // 监听通知错误事件 notification.onerror = () => console.log('通知出现错误');运行时,控制台会直接输出如下信息通知已显示点击通知时,会输出通知被点击当通知关闭时,会输出通知被关闭3、发送Notification通知代码结合上面的介绍,下面给出发送通知的参考代码,具体如下:function sendNotification(title, body, icon, callback) { // 先检查浏览器是否支持 if (!('Notification' in window)) { // IE浏览器不支持发送Notification通知! return; } if (Notification.permission === 'denied') { // 如果用户已拒绝显示通知 return; } if (Notification.permission === 'granted') { //用户已授权,直接发送通知 notify(); } else { // 默认,先向用户询问是否允许显示通知 Notification.requestPermission(function(permission) { // 如果用户同意,就可以直接发送通知 if (permission === 'granted') { notify(); } }); } function notify() { let notification = new Notification(title, { icon: icon, body: body }); notification.onclick = function() { callback && callback(); console.log('单击通知框') } notification.onclose = function() { console.log('关闭通知框'); }; } }下面来测试一下:sendNotification('下班通知', '今天周五,还有十分钟下班', 'http://localhost/coder/favicon.ico');运行后,通知的效果如下:参考资料:https://developer.mozilla.org/zh-CN/docs/Web/API/notificationhttps://developer.mozilla.org/zh-CN/docs/Web/API/Notifications_API
2023年01月12日
789 阅读
0 评论
0 点赞
2023-01-12
JS常用监听事件【监听键盘、触控、鼠标、多媒体、打印、剪贴板、表单等事件】
下文中按照监听类型列举了js支持的监听事件名称及解释,内容来源于网络,如有缺失或错误欢迎各位留言指正。鼠标事件click 当用户点击某个对象时调用的事件句柄。contextmenu 在用户点击鼠标右键打开上下文菜单时触发dblclick 当用户双击某个对象时调用的事件句柄。mousedown 鼠标按钮被按下。mouseenter 当鼠标指针移动到元素上时触发。mouseleave 当鼠标指针移出元素时触发mousemove 鼠标被移动。mouseover 鼠标移到某元素之上。mouseout 鼠标从某元素移开。mouseup 鼠标按键被松开。键盘事件keydown 某个键盘按键被按下。keypress 某个键盘按键被按下并松开。keyup 某个键盘按键被松开。触控事件touchstart 用户开始触摸时触发,它的target属性返回发生触摸的元素节点。touchend 用户不再接触触摸屏时(或者移出屏幕边缘时)触发,它的target属性与touchstart事件一致的,就是开始触摸时所在的元素节点。它的changedTouches属性返回一个TouchList实例,包含所有不再触摸的触摸点(即Touch实例对象)。touchmove 用户移动触摸点时触发,它的target属性与touchstart事件一致。如果触摸的半径、角度、力度发生变化,也会触发该事件。touchcancel 触摸点取消时触发,比如在触摸区域跳出一个模态窗口(modal window)、触摸点离开了文档区域(进入浏览器菜单栏)、用户的触摸点太多,超过了支持的上限(自动取消早先的触摸点)。框架/对象(Frame/Object)事件abort 图像的加载被中断。 beforeunload 该事件在即将离开页面(刷新或关闭)时触发error 在加载文档或图像时发生错误。hashchange 该事件在当前 URL 的锚部分发生修改时触发。load 一张页面或一幅图像完成加载。pageshow 该事件在用户访问页面时触发pagehide 该事件在用户离开当前网页跳转到另外一个页面时触发resize 窗口或框架被重新调整大小。scroll 当文档被滚动时发生的事件。unload 用户退出页面。表单事件blur 元素失去焦点时触发change 该事件在表单元素的内容改变时触发focus 元素获取焦点时触发focusin 元素即将获取焦点是触发focusout 元素即将失去焦点是触发input 元素获取用户输入是触发reset 表单重置时触发search 用户向搜索域输入文本时触发剪贴板事件copy 该事件在用户拷贝元素内容时触发cut 该事件在用户剪切元素内容时触发paste 该事件在用户粘贴元素内容时触发打印事件afterprint 该事件在页面已经开始打印,或者打印窗口已经关闭时触发beforeprint 该事件在页面即将开始打印时触发拖动事件drag 该事件在元素正在拖动时触发dragend 该事件在用户完成元素的拖动时触发dragenter 该事件在拖动的元素进入放置目标时触发dragleave 该事件在拖动元素离开放置目标时触发dragover 该事件在拖动元素在放置目标上时触发dragstart 该事件在用户开始拖动元素时触发drop 该事件在拖动元素放置在目标区域时触发多媒体(Media)事件abort 事件在视频/音频(audio/video)终止加载时触发。canplay 事件在用户可以开始播放视频/音频(audio/video)时触发。canplaythrough 事件在视频/音频(audio/video)可以正常播放且无需停顿和缓冲时触发。durationchange 事件在视频/音频(audio/video)的时长发生变化时触发。emptied 当前播放列表为空时发生事件ended 事件在视频/音频(audio/video)播放结束时触发。error 事件在视频/音频(audio/video)数据加载期间发生错误时触发。loadeddata 事件在浏览器加载视频/音频(audio/video)当前帧时触发触发。loadedmetadata 事件在指定视频/音频(audio/video)的元数据加载后触发。loadstart 事件在浏览器开始寻找指定视频/音频(audio/video)触发。pause 事件在视频/音频(audio/video)暂停时触发。play 事件在视频/音频(audio/video)开始播放时触发。playing 事件在视频/音频(audio/video)暂停或者在缓冲后准备重新开始播放时触发。progress 事件在浏览器下载指定的视频/音频(audio/video)时触发。ratechange 事件在视频/音频(audio/video)的播放速度发送改变时触发。seeked 事件在用户重新定位视频/音频(audio/video)的播放位置后触发。seeking 事件在用户开始重新定位视频/音频(audio/video)时触发。stalled 事件在浏览器获取媒体数据,但媒体数据不可用时触发。suspend 事件在浏览器读取媒体数据中止时触发。timeupdate 事件在当前的播放位置发送改变时触发。volumechange 事件在音量发生改变时触发。waiting 事件在视频由于要播放下一帧而需要缓冲时触发。动画事件animationend 该事件在 CSS 动画结束播放时触发animationiteration 该事件在 CSS 动画重复播放时触发animationstart 该事件在 CSS 动画开始播放时触发过渡事件transitionend 该事件在 CSS 完成过渡后触发。其他事件message 该事件通过或者从对象(WebSocket, Web Worker, Event Source 或者子 frame 或父窗口)接收到消息时触发online 该事件在浏览器开始在线工作时触发。offline 该事件在浏览器开始离线工作时触发。popstate 该事件在窗口的浏览历史(history` 对象)发生改变时触发。 show 该事件当元素在上下文菜单显示时触发storage 该事件在 Web Storage(HTML 5 Web 存储)更新时触发toggle 该事件在用户打开或关闭 元素时触发wheel 该事件在鼠标滚轮在元素上下滚动时触发
2023年01月12日
1,026 阅读
0 评论
0 点赞
2023-01-12
js中的prototype、__proto__、constructor方法详解
提示:不要排斥,静下心来,认真读完,你就搞懂了!(可以先看一下最后的总结部分再回过头来完整看完)1. 前言 作为一名前端工程师,必须搞懂JS中的prototype、__proto__与constructor属性,相信很多初学者对这些属性存在许多困惑,容易把它们混淆,本文旨在帮助大家理清它们之间的关系并彻底搞懂它们。这里说明一点,__proto__属性的两边是各由两个下划线构成(这里为了方便大家看清,在两下划线之间加入了一个空格:_ _proto_ _,读作“dunder proto”,“double underscore proto”的缩写),实际上,该属性在ES标准定义中的名字应该是[[Prototype]],具体实现是由浏览器代理自己实现,谷歌浏览器的实现就是将[[Prototype]]命名为__proto__,大家清楚这个标准定义与具体实现的区别即可(名字有所差异,功能是一样的),可以通过该方式检测引擎是否支持这个属性:Object.getPrototypeOf({__proto__: null}) === null。本文基于谷歌浏览器(版本 72.0.3626.121)的实验结果所得。 现在正式开始! 让我们从如下一个简单的例子展开讨论,并配以相关的图帮助理解:function Foo() {...}; let f1 = new Foo(); 以上代码表示创建一个构造函数Foo(),并用new关键字实例化该构造函数得到一个实例化对象f1。这里稍微补充一下new操作符将函数作为构造器进行调用时的过程:函数被调用,然后新创建一个对象,并且成了函数的上下文(也就是此时函数内部的this是指向该新创建的对象,这意味着我们可以在构造器函数内部通过this参数初始化值),最后返回该新对象的引用,详细请看:详解JavaScript中的new操作符。虽然是简简单单的两行代码,然而它们背后的关系却是错综复杂的,如下图所示: 看到这图别怕,让我们一步步剖析,彻底搞懂它们! 图的说明:右下角为图例,红色箭头表示__proto__属性指向、绿色箭头表示prototype属性的指向、棕色实线箭头表示本身具有的constructor属性的指向,棕色虚线箭头表示继承而来的constructor属性的指向;蓝色方块表示对象,浅绿色方块表示函数(这里为了更好看清,Foo()仅代表是函数,并不是指执行函数Foo后得到的结果,图中的其他函数同理)。图的中间部分即为它们之间的联系,图的最左边即为例子代码。2. __proto__ 属性 首先,我们需要牢记两点:①__proto__和constructor属性是对象所独有的;② prototype属性是函数所独有的。但是由于JS中函数也是一种对象,所以函数也拥有__proto__和constructor属性,这点是致使我们产生困惑的很大原因之一。上图有点复杂,我们把它按照属性分别拆开,然后进行分析: 第一,这里我们仅留下 __proto__ 属性,它是对象所独有的,可以看到__proto__属性都是由一个对象指向一个对象,即指向它们的原型对象(也可以理解为父对象),那么这个属性的作用是什么呢?它的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(可以理解为父对象)里找,如果父对象也不存在这个属性,则继续往父对象的__proto__属性所指向的那个对象(可以理解为爷爷对象)里找,如果还没找到,则继续往上找…直到原型链顶端null(可以理解为原始人。。。),再往上找就相当于在null上取值,会报错(可以理解为,再往上就已经不是“人”的范畴了,找不到了,到此结束,null为原型链的终点),由以上这种通过__proto__属性来连接对象直到null的一条链即为我们所谓的原型链。 其实我们平时调用的字符串方法、数组方法、对象方法、函数方法等都是靠__proto__继承而来的。3. prototype属性 第二,接下来我们看 prototype 属性: prototype属性,别忘了一点,就是我们前面提到要牢记的两点中的第二点,它是函数所独有的,它是从一个函数指向一个对象。它的含义是函数的原型对象,也就是这个函数(其实所有函数都可以作为构造函数)所创建的实例的原型对象,由此可知:f1.__proto__ === Foo.prototype,它们两个完全一样。那prototype属性的作用又是什么呢?它的作用就是包含可以由特定类型的所有实例共享的属性和方法,也就是让该函数所实例化的对象们都可以找到公用的属性和方法。任何函数在创建的时候,其实会默认同时创建该函数的prototype对象。4. constructor属性 最后,我们来看一下 constructor 属性: constructor属性也是对象才拥有的,它是从一个对象指向一个函数,含义就是指向该对象的构造函数,每个对象都有构造函数(本身拥有或继承而来,继承而来的要结合__proto__属性查看会更清楚点,如下图所示),从上图中可以看出Function这个对象比较特殊,它的构造函数就是它自己(因为Function可以看成是一个函数,也可以是一个对象),所有函数和对象最终都是由Function构造函数得来,所以constructor属性的终点就是Function这个函数。 感谢网友的指出,这里解释一下上段中“每个对象都有构造函数”这句话。这里的意思是每个对象都可以找到其对应的constructor,因为创建对象的前提是需要有constructor,而这个constructor可能是对象自己本身显式定义的或者通过__proto__在原型链中找到的。而单从constructor这个属性来讲,只有prototype对象才有。每个函数在创建的时候,JS会同时创建一个该函数对应的prototype对象,而函数创建的对象.__proto__ === 该函数.prototype,该函数.prototype.constructor===该函数本身,故通过函数创建的对象即使自己没有constructor属性,它也能通过__proto__找到对应的constructor,所以任何对象最终都可以找到其构造函数(null如果当成对象的话,将null除外)。如下: 5. 总结 总结一下:我们需要牢记两点:①__proto__和constructor属性是对象所独有的;② prototype属性是函数所独有的,因为函数也是一种对象,所以函数也拥有__proto__和constructor属性。__proto__属性的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(父对象)里找,一直找,直到__proto__属性的终点null,再往上找就相当于在null上取值,会报错。通过__proto__属性将对象连接起来的这条链路即我们所谓的原型链。prototype属性的作用就是让该函数所实例化的对象们都可以找到公用的属性和方法,即f1.__proto__ === Foo.prototype。constructor属性的含义就是指向该对象的构造函数,所有函数(此时看成对象了)最终的构造函数都指向Function。 本文就此结束了,希望对那些对JS中的prototype、__proto__与constructor属性有困惑的同学有所帮助。 最后,感谢这两篇博文,本文中的部分内容参考自这两篇博文:一张图理解prototype、proto和constructor的三角关系prototype和__proto__的关系是什么?小彩蛋:实现继承(相对完美、优雅)function inherit(Child, Parent) { // 继承原型上的属性 Child.prototype = Object.create(Parent.prototype) // 修复 constructor Child.prototype.constructor = Child // 存储超类 Child.super = Parent // 静态属性继承 if (Object.setPrototypeOf) { // setPrototypeOf es6 Object.setPrototypeOf(Child, Parent) } else if (Child.__proto__) { // __proto__ es6 引入,但是部分浏览器早已支持 Child.__proto__ = Parent } else { // 兼容 IE10 等陈旧浏览器 // 将 Parent 上的静态属性和方法拷贝一份到 Child 上,不会覆盖 Child 上的方法 for (var k in Parent) { if (Parent.hasOwnProperty(k) && !(k in Child)) { Child[k] = Parent[k] } } } }
2023年01月12日
347 阅读
0 评论
0 点赞
2023-01-06
JS使用正则表达式获取小括号、中括号及花括号内容的方法示例
本文实例讲述了JS使用正则表达式获取小括号、中括号及花括号内容的方法。分享给大家供大家参考,具体如下:正则表达式的() [] {}有不同的意思() 是为了提取匹配的字符串。表达式中有几个()就有几个相应的匹配字符串。(\s*)表示连续空格的字符串。[]是定义匹配的字符范围。比如 [a-zA-Z0-9] 表示相应位置的字符要匹配英文字符和数字。[\s]表示空格或者号。{}一般用来表示匹配的长度,比如 \s{3} 表示匹配三个空格,\s[1,3]表示匹配一到三个空格。(0-9) 匹配 '0-9′ 本身。 [0-9] 匹配数字(注意后面有 ,可以为空)[0-9]+ 匹配数字(注意后面有 +,不可以为空){1-9} 写法错误。[0-9]{0,9} 表示长度为 0 到 9 的数字字符串。小括号是用于将基本的单元合成一个大的单元,而中括号就是将多个基本单元组成一个选择域,表示其中一个的意思。例子:小括号例子1、我们想匹配123这个整体(123)就是匹配"123"这个整体,大括号而[123]就是匹配1/2/3(1或者2或者3)再举个面圈教程小编碰到的一个问题例如我们想匹配 多个替换 中间多个 的时候先用中括号[]<p>[ ]*</p>匹配内容的就如下图所示那下面用小括号试试()<p>( )*</p>JS 正则表达式 获取小括号 中括号 花括号内的内容<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>www.nhooo.com JS获取括号内容</title> </head> <body> <script type="text/javascript"> var str="123{xxxx}456[我的]789123[你的]456(1389090)789"; var regex1 = /\((.+?)\)/g; // () 小括号 var regex2 = /\[(.+?)\]/g; // [] 中括号 var regex3 = /\{(.+?)\}/g; // {} 花括号,大括号 // 输出是一个数组 console.log(str.match(regex1)); console.log(str.match(regex2)); console.log(str.match(regex3)); </script> </body> </html>使用在线HTML/CSS/JavaScript代码运行工具http://tools.jb51.net/code/HtmlJsRun测试运行结果如下:附:JAVA正则匹配语句regex =PS:这里再为大家提供2款非常方便的正则表达式工具供大家参考使用:JavaScript正则表达式在线测试工具:http://tools.jb51.net/regex/javascript正则表达式在线生成工具:http://tools.jb51.net/regex/create_reg更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《JavaScript正则表达式技巧大全》、《JavaScript替换操作技巧总结》、《JavaScript查找算法技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》、《JavaScript中json操作技巧总结》、《JavaScript错误与调试技巧总结》及《JavaScript数学运算用法总结》希望本文所述对大家JavaScript程序设计有所帮助。
2023年01月06日
551 阅读
0 评论
0 点赞
2023-01-05
JS正则常用校验大全
手机号(mobile phone)中国(严谨), 根据工信部2019年最新公布的手机号段const reg = /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8}$/; const str = "19119255642"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);Email(邮箱)const reg = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; const str = "90203918@qq.com"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);座机(Tel Phone)电话(国内) 如: 0341-86091234const reg = /^(?:(?:\d{3}-)?\d{8}|^(?:\d{4}-)?\d{7,8})(?:-\d+)?$/; const str = "0936-4211235"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);身份证号(2代,18位数字),最后一位是校验位,可能为数字或字符Xconst reg = /^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/; const str = "12345619991205131x"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);中文姓名const reg = /^(?:[\u4e00-\u9fa5·]{2,16})$/; const str = "韩小韩"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);英文姓名const reg = /(^[a-zA-Z][a-zA-Z\s]{0,20}[a-zA-Z]$)/; const str = "James Han"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);网址(URL)const reg = /^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/; const str = "https://www.vvhan.com"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);必须带端口号的网址(或IP)const reg = /^((ht|f)tps?:\/\/)?[\w-]+(\.[\w-]+)+:\d{1,5}\/?$/; const str = "https://www.vvhan.com:80"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);银行卡号(10到30位, 覆盖对公/私账户)const reg = /^[1-9]\d{9,29}$/; const str = "6222026006705354000"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线组合)const reg = /^[a-zA-Z]\w{4,15}$/; const str = "han_666666"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);中文/汉字const reg = /^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])+$/; const str = "易航博客"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);密码强度校验,最少6位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符const reg = /^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/; const str = "han@666vvx,"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);微信号(wx),6至20位,以字母开头,字母,数字,减号,下划线const reg = /^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/; const str = "kd_-666"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);邮政编码(中国)const reg = /^(0[1-7]|1[0-356]|2[0-7]|3[0-6]|4[0-7]|5[1-7]|6[1-7]|7[0-5]|8[013-6])\d{4}$/; const str = "734500"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);中文和数字const reg = /^((?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])|(\d))+$/; const str = "易航好6啊"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);匹配连续重复的字符const reg = /(.)\1+/; const str = "112233"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);统一社会信用代码const reg = /^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/; const str = "91110108772551611J"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);子网掩码(不包含 0.0.0.0)const reg = /^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(255|254|252|248|240|224|192|128|0)$/; const str = "255.255.255.0"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);车牌号(新能源)const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z](?:((\d{5}[A-HJK])|([A-HJK][A-HJ-NP-Z0-9][0-9]{4}))|[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳])$/; const str = "京AD92035"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);车牌号(非新能源)const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]$/; const str = "京A00599"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);车牌号(新能源+非新能源)const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/; const str = "京A12345D"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);护照(包含香港、澳门)const reg = /(^[EeKkGgDdSsPpHh]\d{8}$)|(^(([Ee][a-fA-F])|([DdSsPp][Ee])|([Kk][Jj])|([Mm][Aa])|(1[45]))\d{7}$)/; const str = "s28233515"; console.log(`校验 ${reg.test(str) ? "正确" : "错误"}`);
2023年01月05日
298 阅读
0 评论
0 点赞
2022-09-16
Windows安装PECL
安装步骤PECL是 The PHP Extension Community Library 缩写。下载go-pear.phar 到 d:/tool/go-pear.phar执行 php d:/tool/go-pear.phar下载地址:http://pear.php.net/go-pear.phar官方文档:https://pear.php.net/manual/en/installation.getting.php关键事项注意事项:第一个一定是选择 local。第一次执行的时候一定要指定 php的路径,输入13弹出对话框选择PHP的目录。之后直接按 Enter 继续。完成!安装过程D:\pear>php d:/tool/go-pear.phar Are you installing a system-wide PEAR or a local copy? (system|local) [system] : local Please confirm local copy by typing 'yes' : yes Below is a suggested file layout for your new PEAR installation. To change individual locations, type the number in front of the directory. Type 'all' to change all of them or simply press Enter to accept these locations. 1. Installation base ($prefix) : D:\pear 2. Temporary directory for processing : D:\pear\tmp 3. Temporary directory for downloads : D:\pear\tmp 4. Binaries directory : D:\pear 5. PHP code directory ($php_dir) : D:\pear\pear 6. Documentation directory : D:\pear\docs 7. Data directory : D:\pear\data 8. User-modifiable configuration files directory : D:\pear\cfg 9. Public Web Files directory : D:\pear\www 10. System manual pages directory : D:\pear\man 11. Tests directory : D:\pear\tests 12. Name of configuration file : D:\pear\pear.ini 13. Path to CLI php.exe : 1-13, 'all' or Enter to continue: 13 php.exe (sapi: cli) found. Below is a suggested file layout for your new PEAR installation. To change individual locations, type the number in front of the directory. Type 'all' to change all of them or simply press Enter to accept these locations. 1. Installation base ($prefix) : D:\pear\ 2. Temporary directory for processing : D:\pear\\tmp 3. Temporary directory for downloads : D:\pear\\tmp 4. Binaries directory : D:\pear\ 5. PHP code directory ($php_dir) : D:\pear\\pear 6. Documentation directory : D:\pear\\docs 7. Data directory : D:\pear\\data 8. User-modifiable configuration files directory : D:\pear\\cfg 9. Public Web Files directory : D:\pear\\www 10. System manual pages directory : D:\pear\\man 11. Tests directory : D:\pear\\tests 12. Name of configuration file : D:\pear\\pear.ini 13. Path to CLI php.exe : D:\php73\ 1-13, 'all' or Enter to continue: Beginning install... Configuration written to D:\pear\\pear.ini... Initialized registry... Preparing to install... installing phar://D:/tool/go-pear.phar/PEAR/go-pear-tarballs/Archive_Tar-1.4.7.t ar... installing phar://D:/tool/go-pear.phar/PEAR/go-pear-tarballs/Console_Getopt-1.4. 2.tar... installing phar://D:/tool/go-pear.phar/PEAR/go-pear-tarballs/PEAR-1.10.9.tar... installing phar://D:/tool/go-pear.phar/PEAR/go-pear-tarballs/Structures_Graph-1. 1.1.tar... installing phar://D:/tool/go-pear.phar/PEAR/go-pear-tarballs/XML_Util-1.4.3.tar. .. install ok: channel://pear.php.net/Archive_Tar-1.4.7 install ok: channel://pear.php.net/Console_Getopt-1.4.2 install ok: channel://pear.php.net/Structures_Graph-1.1.1 install ok: channel://pear.php.net/XML_Util-1.4.3 install ok: channel://pear.php.net/PEAR-1.10.9 PEAR: Optional feature webinstaller available (PEAR's web-based installer) PEAR: Optional feature gtkinstaller available (PEAR's PHP-GTK-based installer) PEAR: Optional feature gtk2installer available (PEAR's PHP-GTK2-based installer) PEAR: To install optional features use "pear install pear/PEAR#featurename" ****************************************************************************** WARNING! The include_path defined in the currently used php.ini does not contain the PEAR PHP directory you just specified: <D:\pear\\pear> If the specified directory is also not in the include_path used by your scripts, you will have problems getting any PEAR packages working. Would you like to alter php.ini <D:\PHP73\php.ini>? [Y/n] : Y php.ini <D:\PHP73\php.ini> include_path updated. Current include path : .;C:\php\pear Configured directory : D:\pear\\pear Currently used php.ini (guess) : D:\PHP73\php.ini Press Enter to continue: ** WARNING! Old version found at C:\Program Files (x86)\Common Files\Oracle\Java \javapath\pear.bat, please remove it or be sure to use the new d:\pear\\pear.bat command The 'pear' command is now at your service at d:\pear\\pear.bat ** The 'pear' command is not currently in your PATH, so you need to ** use 'd:\pear\\pear.bat' until you have added ** 'D:\pear\' to your PATH environment variable. Run it without parameters to see the available actions, try 'pear list' to see what packages are installed, or 'pear help' for help. For more information about PEAR, see: http://pear.php.net/faq.php http://pear.php.net/manual/ Thanks for using go-pear!
2022年09月16日
1,045 阅读
1 评论
0 点赞
2022-07-12
golang的redis操作
安装go-redis v8版本go get github.com/go-redis/redis/v8初始化链接cnt = redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password set DB: 2, // use default DB })设置过期时间设置了时间,并且还没有过期的使用TTL命令可以看见还有多长时间过期。过期的会显示-2ns,没有设置过期时间的会显示-1ns通用判断key是存在fmt.Println(cnt.Exists(ctx, "mykey3").Result())//返回key的数量。不存在就是0模糊遍历Scaniter := cnt.Scan(ctx, 0, "prefix:*", 0).Iterator() for iter.Next(ctx) { fmt.Println("keys", iter.Val()) } if err := iter.Err(); err != nil { panic(err) }模糊查询keyfmt.Println(cnt.Keys(ctx,"t*").Result())Hash 批量写(多个field写入同一个key下)count,err:=cnt.HMSet(ctx,"mykey1",map[string]string{"name3":"达芬奇","name4":"kobe"}).Result() count,err=cnt.HMSet(ctx,"mykey1",[]string{"name5","达芬奇2","name6","kobe2"}).Result() count,err=cnt.HMSet(ctx,"mykey1","name7","达芬奇3","name8","kobe4").Result()批量读(读取同一个key的下的多个field)r,err:=cnt.HMGet(ctx,"mykey1","name","name2","name3").Result() //读取同一个key的下的多个field if err !=nil { fmt.Println(err) } fmt.Println(r) //r是一个[]interface类型的删除cnt.HDel(ctx,"mykey1","name").Result()//会返回删除的字段的数量判断是否存在key或者对应key的fieldfmt.Println(cnt.HExists(ctx,"mykey1","name2").Result())获取一个key下的所有fieldfmt.Println(cnt.HGetAll(ctx,"mykey1").Result()) //返回map[string]string给某个field增加值//要被增加的field的value必须是对应的数值类型才可以 fmt.Println(cnt.HIncrBy(ctx,"mykey1","name1",2).Result()) //第四个参数是指要加多少,返回被修改后的field的value的值 fmt.Println(cnt.HIncrByFloat(ctx,"mykey1","name9",1.0000).Result())获取指定key的所有fieldfmt.Println(cnt.HKeys(ctx,"mykey1").Result())//返回string数组模糊查询指定key的field//HScan(ctx,"mykey1",游标-从哪开始,要匹配的字符,返回几个数据) fmt.Println(cnt.HScan(ctx,"mykey1",0,"s*",10).Result())//返回规定数量的匹配的field的数组和游标值没有就创建,有了就不动fmt.Println(cnt.HSetNX(ctx,"mykey2","age2","2").Result())//返回是否有新的创建成功获取指定key的所有field的valuefmt.Println(cnt.HVals(ctx, "mykey1").Result())//返回value的数组
2022年07月12日
282 阅读
0 评论
0 点赞
2022-07-06
PHP面向对象中魔术方法相关的使用
魔术方法是PHP面向对象中特有的特性。它们在特定的情况下被触发,都是以双下划线开头,你可以把它们理解为钩子,利用模式方法可以轻松实现PHP面向对象中重载(Overloading即动态创建类属性和方法)。魔术方法很多还是成对出现的,以下列出目前PHP中所有的模式方法。魔术方法的用法:__construct : 构造方法 在类实例化的时候,会自动调用该魔术方法,进行类的初始化;子类继承父类时__construct 的用法: ①自己没有,会自动去父类中去找 ②自己有,自己初始化时会触发自己的__construct方法进行初始化操作; ③如果有还想调用父类的__construct方法, 语法 parent::__construct;__construct,__destruct __constuct构建对象的时被调用; __destruct明确销毁对象或脚本结束时被调用;__get,__set__set当给不可访问或不存在属性赋值时被调用__get读取不可访问或不存在属性时被调用__isset,__unset__isset对不可访问或不存在的属性调用isset()或empty()时被调用__unset对不可访问或不存在的属性进行unset时被调用__call,__callStatic__call调用不可访问或不存在的方法时被调用__callStatic调用不可访问或不存在的静态方法时被调用__sleep,__wakeup__sleep当使用serialize时被调用,当你不需要保存大对象的所有数据时很有用__wakeup当使用unserialize时被调用,可用于做些对象的初始化操作__clone 进行对象clone时被调用,用来调整对象的克隆行为__toString 当一个类被转换成字符串时被调用__invoke 当以函数方式调用对象时被调用__set_state 当调用var_export()导出类时,此静态方法被调用。用__set_state的返回值做为var_export的返回值。<?php class Magic { public $var = 'test'; //构造函数,在创建对象的时候调用 public function __construct() { echo '__construct called'.PHP_EOL; } //某个对象的引用都被删除、对象被销毁、调用exit()后、脚本关闭时被调用 public function __destruct() { echo '__destruct called'.PHP_EOL; } //当给不可访问或不存在属性赋值时被调用 public function __set($name, $value) { echo $name.'-'.$value; echo '__set called'.PHP_EOL; } //读取不可访问或不存在属性时被调用 public function __get($name) { echo $name; echo '__get called'.PHP_EOL; } //调用不可访问或不存在的方法时被调用 public function __call($name, $arguments) { echo $name . '-' . implode(',', $arguments); echo '__call called'.PHP_EOL; } //调用不可访问或不存在的静态方法时被调用 public static function __callStatic($name, $arguments) { echo $name . '-' . implode(',', $arguments); echo '__callStatic called'.PHP_EOL; } //对不可访问或不存在的属性调用isset()或empty()时被调用 public function __isset($name) { echo $name; echo '__isset called'.PHP_EOL; return true; } //对不可访问或不存在的属性进行unset时被调用 public function __unset($name) { echo $name; echo '__unset called'.PHP_EOL; } //serialize时被调用,当你不需要保存大对象的所有数据时很有用 public function __sleep() { echo '__sleep called'.PHP_EOL; return array('var1111111111'); } //unserialize时被调用,可用于做些对象的初始化操作 public function __wakeup() { echo '__wakeup called'.PHP_EOL; $this->var = 'test after wakeup'; } //当一个类被转换成字符串时被调用 public function __toString() { return '__toString called'.PHP_EOL; } //进行对象clone时被调用,用来调整对象的克隆行为 public function __clone() { echo '__clone called'.PHP_EOL; } //当以函数方式调用对象时被调用 public function __invoke() { echo '__invoke called'.PHP_EOL; } //当调用var_export()导出类时,此静态方法被调用。用__set_state的返回值做为var_export的返回值。 public static function __set_state($arr) { return '__set_state called'.PHP_EOL; } //当调用var_dump()打印对象时被调用(当你不想打印所有属性)适用于PHP5.6版本 public function __debuginfo($arr) { echo '__debuginfo called'.PHP_EOL; return array( 'var' => 'test fro __debuginfo' ); } } $m = new Magic(); //__construct()被调用 $m->not_exist_property = test; //__set()被调用 echo $m->not_exist_property;//__get()被调用 $m->abc(1,2,3); //__call()被调用 echo isset($m->not_exist_property); //__isset()被调用,返回bool值 unset($m->not_exist_property); //__unset()被调用 echo $tmp = serialize($m); //__sleep()被调用 unserialize($tmp); //__wakeup()被调用 $m1 = clone $m; //__clone()被调用,对象默认是引用传递,使用clone关键词则可实现对象复制 $m(); //__invoke() eval( '$m2 = ' . var_export ( $m , true ) . ';' );var_dump($m2); var_dump($m); //最后__destruct()被调用 /* 结果: __construct called not_exist_property-test__set called not_exist_property__get called abc-1,2,3__call called not_exist_property__isset called 1not_exist_property__unset called __sleep called O:5:"Magic":1:{s:13:"var1111111111";N;}__wakeup called __destruct called __clone called __invoke called string(20) "__set_state called " class Magic#1 (1) { public $var => string(4) "test" } __destruct called __destruct called */
2022年07月06日
182 阅读
0 评论
0 点赞
2019-12-19
Laravel 解决跨域和OPTIONS请求问题
建立或现用公共中间件中handle方法改为如下代码public function handle(Request $request, Closure $next) { /** * 用于跨域调用 */ if($request->isMethod('OPTIONS')){ $response = response('',200); }else{ $response = $next($request); } if($referrer = $request->server('HTTP_REFERER') ?? $request->server('HTTP_ORIGIN')){ preg_match('/^(http[s]?:\/\/)?([^\/]+)/i', $referrer, $match); $response->header('Access-Control-Allow-Origin',"{$match[0]}"); $response->header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, DELETE'); $response->header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization, Cookies, Token,content-type'); $response->header('Access-Control-Allow-Credentials', 'true'); $response->header('Cache-Control', 'no-store'); } return $response; }
2019年12月19日
134 阅读
0 评论
0 点赞
2019-11-15
php http_post 模拟(GET|POST|DELETE|PUT)提交相关函数分享
if (!function_exists('http_post')) { /** * * 模拟提交数据 * @param $url * @param string $data null|string|jsonString|array|object * @param string $method GET|POST|DELETE|PUT * @param string $type json|form-data * @param array $header array_header * @return bool|string */ function http_post($url,$data="",$method = 'POST',$type='json',$header=[]) { //初始化 $ch = curl_init(); $headers = [ 'form-data' => ['Content-Type: multipart/form-data'], 'json' => ['Content-Type: application/json'], ]; function toData(&$arr){ $post=[]; foreach ($arr AS $key=>$value){ array_push($post,"{$key}=".urlencode($value)); } $arr = join('&',$post); } $Header=[]; if(!$data) $method='GET'; if($method == 'GET'){ if($data){ if(is_array($data)||is_object($data)) toData($data); $querystring = http_build_query($data); $url = $url.(strpos($url,'?') !== false?'&':'?').$querystring; } }else{ if(is_array($data)||is_object($data)){ $type='form-data'; toData($data); } isset($headers[$type]) && $Header=$headers[$type]; } curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 执行后不直接打印出来 if($method == 'POST'){ curl_setopt($ch, CURLOPT_CUSTOMREQUEST,'POST'); // 请求方式 curl_setopt($ch, CURLOPT_POST, true); // post提交 curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // post的变量 } if($method == 'PUT'){ curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "PUT"); curl_setopt($ch, CURLOPT_POSTFIELDS,$data); } if($method == 'DELETE'){ curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "DELETE"); curl_setopt($ch, CURLOPT_POSTFIELDS,$data); } if(stripos($url,"https://")!==FALSE){ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 不从证书中检查SSL加密算法是否存在 } curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge($Header,$header)); $output = curl_exec($ch); //执行并获取HTML文档内容 $aStatus = curl_getinfo($ch); curl_close($ch); if(intval($aStatus["http_code"])==200){ return $output; }else{ return false; } } }
2019年11月15日
177 阅读
0 评论
0 点赞
2017-03-20
MySQL函数和操作符(超详细,备着查找)
一、操作符1.1 操作符优先级以下列表显示了操作符优先级的由低到高的顺序。排列在同一行的操作符具有相同的优先级。操作符优先级:=1||, OR, XOR2&&, AND3NOT4BETWEEN, CASE, WHEN, THEN, ELSE5=, <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN6|7&8<<, >>9-, +10*, /, DIV, %, MOD11^12- (一元减号), ~ (一元比特反转)12!13BINARY, COLLATE14注释:假如 HIGH_NOT_PRECEDENCE SQL 模式被激活,则 NOT 的优先级同 the ! 操作符相同。1.2 圆括号( ... )使用括弧来规定表达式的运算顺序,例如:mysql> SELECT 1+2*3; -> 7 mysql> SELECT (1+2)*3; -> 91.3 比较函数和操作符比较运算产生的结果为1(TRUE)、0 (FALSE)或 NULL。这些运算可用于数字和字符串。根据需要,字符串可自动转换为数字,而数字也可自动转换为字符串。本节中的一些函数 (如LEAST()和GREATEST()) 的所得值不包括 1 (TRUE)、 0 (FALSE)和 NULL。然而,其所得值乃是基于按照下述规则运行的比较运算:MySQL按照以下规则进行数值比较:若有一个或两个参数为 NULL,除非NULL-safe <=> 等算符,则比较运算的结果为NULL。若同一个比较运算中的两个参数都是字符串,则按照字符串进行比较。若两个参数均为整数,则按照整数进行比较。十六进制值在不需要作为数字进行比较时,则按照二进制字符串进行处理。假如参数中的一个为 TIMESTAMP 或 DATETIME 列,而其它参数均为常数, 则在进行比较前将常数转为 timestamp。这样做的目的是为了使ODBC的进行更加顺利。 注意,这不适合IN()中的参数!为了更加可靠,在进行对比时通常使用完整的 datetime/date/time字符串。在其它情况下,参数作为浮点数进行比较。在默认状态下,字符串比较不区分大小写,并使用现有字符集(默认为cp1252 Latin1,同时对英语也适合)。为了进行比较,可使用CAST()函数将某个值转为另外一种类型。 使用CONVERT()将字符串值转为不同的字符集。以下例子说明了比较运算中将字符串转为数字的过程:mysql> SELECT 1 > '6x'; -> 0 mysql> SELECT 7 > '6x'; -> 1 mysql> SELECT 0 > 'x6'; -> 0 mysql> SELECT 0 = 'x6'; -> 1 注意,在将一个字符串列同一个数字进行比较时, MySQL 不能使用列中的索引进行快速查找。假如str_col 是一个编入索引的字符串列,则在以下语句中,索引不能执行查找功能:SELECT * FROM tbl_name WHERE str_col=1;其原因是许多不同的字符串都可被转换为数值 1: '1'、'1a'、 ……= 等于:mysql> SELECT 1 = 0; -> 0 mysql> SELECT '0' = 0; -> 1 mysql> SELECT '0.0' = 0; -> 1 mysql> SELECT '0.01' = 0; -> 0 mysql> SELECT '.01' = 0.01; -> 1 <=> NULL-safe equal.这个操作符和=操作符执行相同的比较操作,不过在两个操作码均为NULL时,其所得值为1而不为NULL,而当一个操作码为NULL时,其所得值为0而不为NULL。mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL; -> 1, 1, 0 mysql> SELECT 1 = 1, NULL = NULL, 1 = NULL; -> 1, NULL, NULL<> 或 != 不等于:mysql> SELECT '.01' <> '0.01'; -> 1 mysql> SELECT .01 <> '0.01'; -> 0 mysql> SELECT 'zapp' <> 'zappp'; -> 1<= 小于等于:mysql> SELECT 0.1 <= 2; -> 1< 小于:mysql> SELECT 2 < 2; -> 0>= 大于等于:mysql> SELECT 2 >= 2; -> 1 > 大于:mysql> SELECT 2 > 2; -> 0IS boolean_value 和 IS NOT boolean_value根据一个布尔值来检验一个值,在这里,布尔值可以是TRUE、FALSE或UNKNOWN。mysql> SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN; -> 1, 1, 1 mysql> SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN; -> 1, 1, 0 IS NULL 和 IS NOT NULL检验一个值是否为 NULL。mysql> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL; -> 0, 0, 1 mysql> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL; -> 1, 1, 0 expr BETWEEN min AND max假如expr大于或等于 min 且expr 小于或等于max, 则BETWEEN 的返回值为1,或是0。若所有参数都是同一类型,则上述关系相当于表达式 (min <= expr AND expr <= max)。其它类型的转换根据本章开篇所述规律进行,且适用于3种参数中任意一种。mysql> SELECT 1 BETWEEN 2 AND 3; -> 0 mysql> SELECT 'b' BETWEEN 'a' AND 'c'; -> 1 mysql> SELECT 2 BETWEEN 2 AND '3'; -> 1 mysql> SELECT 2 BETWEEN 2 AND 'x-3'; -> 0 expr NOT BETWEEN min AND max这相当于NOT(expr BETWEEN min AND max)。COALESCE(value,...)返回值为列表当中的第一个非 NULL值,在没有非NULL 值得情况下返回值为 NULL 。mysql> SELECT COALESCE(NULL,1); -> 1 mysql> SELECT COALESCE(NULL,NULL,NULL); -> NULL GREATEST(value1,value2,...)当有2或多个参数时,返回值为最大(最大值的)参数。比较参数所依据的规律同LEAST()相同。mysql> SELECT GREATEST(2,0); -> 2 mysql> SELECT GREATEST(34.0,3.0,5.0,767.0); -> 767.0 mysql> SELECT GREATEST('B','A','C'); -> 'C' 在没有自变量为NULL的情况下,GREATEST()的返回值为NULL。expr IN (value,...)若expr 为IN列表中的任意一个值,则其返回值为 1 , 否则返回值为0。假如所有的值都是常数,则其计算和分类根据 expr 的类型进行。这时,使用二分搜索来搜索信息。如IN值列表全部由常数组成,则意味着IN 的速度非常之快。如expr 是一个区分大小写的字符串表达式,则字符串比较也按照区分大小写的方式进行。mysql> SELECT 2 IN (0,3,5,'wefwf'); -> 0 mysql> SELECT 'wefwf' IN (0,3,5,'wefwf'); -> 1 IN 列表中所列值的个数仅受限于 max_allowed_packet 值。为了同SQL 标准相一致,在左侧表达式为NULL的情况下,或是表中找不到匹配项或是表中一个表达式为NULL 的情况下,IN的返回值均为NULL。IN() 语构也可用书写某些类型的子查询。expr NOT IN (value,...)这与NOT (expr IN (value,...))相同。ISNULL(expr)如expr 为NULL,那么ISNULL() 的返回值为 1,否则返回值为 0。mysql> SELECT ISNULL(1+1); -> 0 mysql> SELECT ISNULL(1/0); -> 1 使用= 的NULL 值对比通常是错误的。INTERVAL(N,N1,N2,N3,...)假如N < N1,则返回值为0;假如N < N2 等等,则返回值为1;假如N 为NULL,则返回值为 -1 。所有的参数均按照整数处理。为了这个函数的正确运行,必须满足 N1 < N2 < N3 < ……< Nn 。其原因是使用了二分查找(极快速)。mysql> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200); -> 3 mysql> SELECT INTERVAL(10, 1, 10, 100, 1000); -> 2 mysql> SELECT INTERVAL(22, 23, 30, 44, 200); -> 0 LEAST(value1,value2,...)在有两个或多个参数的情况下, 返回值为最小 (最小值) 参数。用一下规则将自变量进行对比:假如返回值被用在一个 INTEGER 语境中,或是所有参数均为整数值,则将其作为整数值进行比较。假如返回值被用在一个 REAL语境中,或所有参数均为实值,则 将其作为实值进行比较。假如任意一个参数是一个区分大小写的字符串,则将参数按照区分大小写的字符串进行比较。在其它情况下,将参数作为区分大小写的字符串进行比较。假如任意一个自变量为NULL,则 LEAST()的返回值为NULL 。mysql> SELECT LEAST(2,0); -> 0 mysql> SELECT LEAST(34.0,3.0,5.0,767.0); -> 3.0 mysql> SELECT LEAST('B','A','C'); -> 'A' 注意,上面的转换规则在一些边界情形中会产生一些奇特的结果:mysql> SELECT CAST(LEAST(3600, 9223372036854775808.0) as SIGNED); -> -9223372036854775808 发生这种情况的原因是MySQL在整数语境中读取9223372036854775808.0。整数表示法不利于保存数值,因此它包括一个带符号整数。1.4 逻辑操作符在SQL中,所有逻辑 操作符的求值所得结果均为 TRUE、FALSE或 NULL (UNKNOWN)。在 MySQL中,它们体现为 1 (TRUE)、 0 (FALSE)和 NULL。其大多数都与不同的数据库SQL通用,然而一些服务器对TRUE的返回值可能是任意一个非零值。NOT !逻辑 NOT。当操作数为0 时,所得值为 1 ;当操作数为非零值时,所得值为 0 ,而当操作数为NOT NULL时,所得的返回值为 NULL。mysql> SELECT NOT 10; -> 0 mysql> SELECT NOT 0; -> 1 mysql> SELECT NOT NULL; -> NULL mysql> SELECT ! (1+1); -> 0 mysql> SELECT ! 1+1; -> 1 最后一个例子产生的结果为 1,原因是表达式的计算方式和(!1)+1相同。AND &&逻辑AND。当所有操作数均为非零值、并且不为NULL时,计算所得结果为 1 ,当一个或多个操作数为0 时,所得结果为 0 ,其余情况返回值为 NULL 。mysql> SELECT 1 && 1; -> 1 mysql> SELECT 1 && 0; -> 0 mysql> SELECT 1 && NULL; -> NULL mysql> SELECT 0 && NULL; -> 0 mysql> SELECT NULL && 0; -> 0 OR ||逻辑 OR。当两个操作数均为非 NULL值时,如有任意一个操作数为非零值,则结果为1,否则结果为0。当有一个操作数为NULL时,如另一个操作数为非零值,则结果为1,否则结果为 NULL 。假如两个操作数均为 NULL,则所得结果为 NULL。mysql> SELECT 1 || 1; -> 1 mysql> SELECT 1 || 0; -> 1 mysql> SELECT 0 || 0; -> 0 mysql> SELECT 0 || NULL; -> NULL mysql> SELECT 1 || NULL; -> 1XOR逻辑XOR。当任意一个操作数为 NULL时,返回值为NULL。对于非 NULL 的操作数,假如一个奇数操作数为非零值,则计算所得结果为 1 ,否则为 0 。mysql> SELECT 1 XOR 1; -> 0 mysql> SELECT 1 XOR 0; -> 1 mysql> SELECT 1 XOR NULL; -> NULL mysql> SELECT 1 XOR 1 XOR 1; -> 1 a XOR b 的计算等同于 (a AND (NOT b)) OR ((NOT a)和 b)。二、控制流程函数CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...] [ELSE result] END CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END 在第一个方案的返回结果中, value=compare-value。而第二个方案的返回结果是第一种情况的真实结果。如果没有匹配的结果值,则返回结果为ELSE后的结果,如果没有ELSE 部分,则返回值为 NULL。mysql> SELECT CASE 1 WHEN 1 THEN 'one' -> WHEN 2 THEN 'two' ELSE 'more' END; -> 'one' mysql> SELECT CASE WHEN 1>0 THEN 'true' ELSE 'false' END; -> 'true' mysql> SELECT CASE BINARY 'B' -> WHEN 'a' THEN 1 WHEN 'b' THEN 2 END; -> NULL 一个CASE表达式的默认返回值类型是任何返回值的相容集合类型,但具体情况视其所在语境而定。如果用在字符串语境中,则返回结果味字符串。如果用在数字语境中,则返回结果为十进制值、实值或整数值。IF(expr1,expr2,expr3)如果 expr1 是TRUE (expr1 <> 0 and expr1 <> NULL),则 IF()的返回值为expr2; 否则返回值则为 expr3。IF() 的返回值为数字值或字符串值,具体情况视其所在语境而定。mysql> SELECT IF(1>2,2,3); -> 3 mysql> SELECT IF(1<2,'yes ','no'); -> 'yes' mysql> SELECT IF(STRCMP('test','test1'),'no','yes'); -> 'no' 如果expr2 或expr3中只有一个明确是 NULL,则IF() 函数的结果类型 为非NULL表达式的结果类型。expr1 作为一个整数值进行计算,就是说,假如你正在验证浮点值或字符串值, 那么应该使用比较运算进行检验。mysql> SELECT IF(0.1,1,0); -> 0 mysql> SELECT IF(0.1<>0,1,0); -> 1 在所示的第一个例子中,IF(0.1)的返回值为0,原因是 0.1 被转化为整数值,从而引起一个对 IF(0)的检验。这或许不是你想要的情况。在第二个例子中,比较检验了原始浮点值,目的是为了了解是否其为非零值。比较结果使用整数。IF() (这一点在其被储存到临时表时很重要 ) 的默认返回值类型按照以下方式计算:假如expr2 和expr3 都是字符串,且其中任何一个字符串区分大小写,则返回结果是区分大小写。IFNULL(expr1,expr2)假如expr1 不为 NULL,则 IFNULL() 的返回值为 expr1; 否则其返回值为 expr2。IFNULL()的返回值是数字或是字符串,具体情况取决于其所使用的语境。mysql> SELECT IFNULL(1,0); -> 1 mysql> SELECT IFNULL(NULL,10); -> 10 mysql> SELECT IFNULL(1/0,10); -> 10 mysql> SELECT IFNULL(1/0,'yes'); -> 'yes' IFNULL(expr1,expr2)的默认结果值为两个表达式中更加“通用”的一个,顺序为STRING、 REAL或 INTEGER。假设一个基于表达式的表的情况, 或MySQL必须在内存储器中储存一个临时表中IFNULL()的返回值:CREATE TABLE tmp SELECT IFNULL(1,'test') AS test; 在这个例子中,测试列的类型为 CHAR(4)。NULLIF(expr1,expr2)如果expr1 = expr2 成立,那么返回值为NULL,否则返回值为 expr1。这和CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END相同。mysql> SELECT NULLIF(1,1); -> NULL mysql> SELECT NULLIF(1,2); -> 1 注意,如果参数不相等,则 MySQL 两次求得的值为 expr1 。三、字符串函数假如结果的长度大于 max_allowed_packet 系统变量的最大值时,字符串值函数的返回值为NULL。对于在字符串位置操作的函数,第一个位置的编号为 1。ASCII(str)返回值为字符串str 的最左字符的数值。假如str为空字符串,则返回值为 0 。假如str 为NULL,则返回值为 NULL。 ASCII()用于带有从 0到255的数值的字符。mysql> SELECT ASCII('2'); -> 50 mysql> SELECT ASCII(2); -> 50 mysql> SELECT ASCII('dx'); -> 100见 ORD()函数。BIN(N)返回值为N的二进制值的字符串表示,其中 N 为一个longlong (BIGINT) 数字。这等同于 CONV(N,10,2)。假如N 为NULL,则返回值为 NULL。mysql> SELECT BIN(12); -> '1100'BIT_LENGTH(str)返回值为二进制的字符串str 长度。mysql> SELECT BIT_LENGTH('text'); -> 32CHAR(N,... [USING charset])CHAR()将每个参数N理解为一个整数,其返回值为一个包含这些整数的代码值所给出的字符的字符串。NULL值被省略。mysql> SELECT CHAR(77,121,83,81,'76'); -> 'MySQL' mysql> SELECT CHAR(77,77.3,'77.3'); -> 'MMM'大于 255的CHAR()参数被转换为多结果字符。 例如,CHAR(256) 相当于 CHAR(1,0), 而CHAR(256*256) 则相当于 CHAR(1,0,0):mysql> SELECT HEX(CHAR(1,0)), HEX(CHAR(256)); mysql> SELECT HEX(CHAR(1,0,0)), HEX(CHAR(256*256)); CHAR()的返回值为一个二进制字符串。可选择使用USING语句产生一个给出的字符集中的字符串:mysql> SELECT CHARSET(CHAR(0x65)), CHARSET(CHAR(0x65 USING utf8)); mysql> SELECT CHARSET(CHAR(0x65)), CHARSET(CHAR(0x65 USING utf8)); 如果 USING已经产生,而结果字符串不符合给出的字符集,则会发出警告。 同样,如果严格的SQL模式被激活,则CHAR()的结果会成为 NULL。CHAR_LENGTH(str)返回值为字符串str 的长度,长度的单位为字符。一个多字节字符算作一个单字符。对于一个包含五个二字节字符集, LENGTH()返回值为 10, 而CHAR_LENGTH()的返回值为5。CHARACTER_LENGTH(str)CHARACTER_LENGTH()是CHAR_LENGTH()的同义词。COMPRESS(string_to_compress)压缩一个字符串。这个函数要求 MySQL已经用一个诸如zlib的压缩库压缩过。 否则,返回值始终是NULL。UNCOMPRESS() 可将压缩过的字符串进行解压缩。mysql> SELECT LENGTH(COMPRESS(REPEAT('a',1000))); -> 21 mysql> SELECT LENGTH(COMPRESS('')); -> 0 mysql> SELECT LENGTH(COMPRESS('a')); -> 13 mysql> SELECT LENGTH(COMPRESS(REPEAT('a',16))); -> 15 压缩后的字符串的内容按照以下方式存储:空字符串按照空字符串存储。非空字符串未压缩字符串的四字节长度进行存储(首先为低字节),后面是压缩字符串。如果字符串以空格结尾,就会在后加一个"."号,以防止当结果值是存储在CHAR或VARCHAR类型的字段列时,出现自动把结尾空格去掉的现象。(不推荐使用 CHAR 或VARCHAR 来存储压缩字符串。最好使用一个 BLOB 列代替)。CONCAT(str1,str2,...)返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL。或许有一个或多个参数。 如果所有参数均为非二进制字符串,则结果为非二进制字符串。 如果自变量中含有任一二进制字符串,则结果为一个二进制字符串。一个数字参数被转化为与之相等的二进制字符串格式;若要避免这种情况,可使用显式类型 cast, 例如: SELECT CONCAT(CAST(int_col AS CHAR), char_col)mysql> SELECT CONCAT('My', 'S', 'QL'); -> 'MySQL' mysql> SELECT CONCAT('My', NULL, 'QL'); -> NULL mysql> SELECT CONCAT(14.3); -> '14.3' CONCAT_WS(separator,str1,str2,...)CONCAT_WS() 代表 CONCAT With Separator ,是CONCAT()的特殊形式。 第一个参数是其它参数的分隔符。分隔符的位置放在要连接的两个字符串之间。分隔符可以是一个字符串,也可以是其它参数。如果分隔符为 NULL,则结果为 NULL。函数会忽略任何分隔符参数后的 NULL 值。mysql> SELECT CONCAT_WS(',','First name','Second name','Last Name'); -> 'First name,Second name,Last Name' mysql> SELECT CONCAT_WS(',','First name',NULL,'Last Name'); -> 'First name,Last Name' CONCAT_WS()不会忽略任何空字符串。 (然而会忽略所有的 NULL)。CONV(N,from_base,to_base)不同数基间转换数字。返回值为数字的N字符串表示,由from_base基转化为 to_base 基。如有任意一个参数为NULL,则返回值为 NULL。自变量 N 被理解为一个整数,但是可以被指定为一个整数或字符串。最小基数为 2 ,而最大基数则为 36。 If to_base 是一个负数,则 N 被看作一个带符号数。否则, N 被看作无符号数。 CONV() 的运行精确度为 64比特。mysql> SELECT CONV('a',16,2); -> '1010' mysql> SELECT CONV('6E',18,8); -> '172' mysql> SELECT CONV(-17,10,-18); -> '-H' mysql> SELECT CONV(10+'10'+'10'+0xa,10,10); -> '40' ELT(N,str1,str2,str3,...)若N = 1,则返回值为 str1 ,若N = 2,则返回值为 str2 ,以此类推。 若N 小于1或大于参数的数目,则返回值为 NULL 。 ELT() 是 FIELD()的补数。mysql> SELECT ELT(1, 'ej', 'Heja', 'hej', 'foo'); -> 'ej' mysql> SELECT ELT(4, 'ej', 'Heja', 'hej', 'foo'); -> 'foo' EXPORT_SET(bits,on,off[,separator[,number_of_bits]])返回值为一个字符串,其中对于bits值中的每个位组,可以得到一个 on 字符串,而对于每个清零比特位,可以得到一个off 字符串。bits 中的比特值按照从右到左的顺序接受检验 (由低位比特到高位比特)。字符串被分隔字符串分开(默认为逗号‘,’),按照从左到右的顺序被添加到结果中。number_of_bits 会给出被检验的二进制位数 (默认为 64)。mysql> SELECT EXPORT_SET(5,'Y','N',',',4); -> 'Y,N,Y,N' mysql> SELECT EXPORT_SET(6,'1','0',',',10); -> '0,1,1,0,0,0,0,0,0,0' FIELD(str,str1,str2,str3,...)返回值为str1, str2, str3,……列表中的str 指数。在找不到str 的情况下,返回值为 0 。如果所有对于FIELD() 的参数均为字符串,则所有参数均按照字符串进行比较。如果所有的参数均为数字,则按照数字进行比较。否则,参数按照双倍进行比较。如果str 为NULL,则返回值为0 ,原因是NULL不能同任何值进行同等比较。FIELD() 是ELT()的补数。mysql> SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo'); -> 2 mysql> SELECT FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo'); -> 0 FIND_IN_SET(str,strlist)假如字符串str 在由N 子链组成的字符串列表strlist 中, 则返回值的范围在 1 到 N 之间 。一个字符串列表就是一个由一些被‘,’符号分开的自链组成的字符串。如果第一个参数是一个常数字符串,而第二个是type SET列,则 FIND_IN_SET() 函数被优化,使用比特计算。如果str不在strlist 或strlist 为空字符串,则返回值为 0 。如任意一个参数为NULL,则返回值为 NULL。 这个函数在第一个参数包含一个逗号(‘,’)时将无法正常运行。mysql> SELECT FIND_IN_SET('b','a,b,c,d'); -> 2 FORMAT(X,D)将number X设置为格式 '#,###,###.##', 以四舍五入的方式保留到小数点后D位, 而返回结果为一个字符串。HEX(N_or_S)如果N_OR_S 是一个数字,则返回一个 十六进制值 N 的字符串表示,在这里, N 是一个longlong (BIGINT)数。这相当于 CONV(N,10,16)。如果N_OR_S 是一个字符串,则返回值为一个N_OR_S的十六进制字符串表示, 其中每个N_OR_S 里的每个字符被转化为两个十六进制数字。mysql> SELECT HEX(255); -> 'FF' mysql> SELECT 0x616263; -> 'abc' mysql> SELECT HEX('abc'); -> 616263 INSERT(str,pos,len,newstr)返回字符串 str, 其子字符串起始于 pos 位置和长期被字符串 newstr取代的len 字符。 如果pos 超过字符串长度,则返回值为原始字符串。 假如len的长度大于其它字符串的长度,则从位置pos开始替换。若任何一个参数为null,则返回值为NULL。mysql> SELECT INSERT('Quadratic', 3, 4, 'What'); -> 'QuWhattic' mysql> SELECT INSERT('Quadratic', -1, 4, 'What'); -> 'Quadratic' mysql> SELECT INSERT('Quadratic', 3, 100, 'What'); -> 'QuWhat' 这个函数支持多字节字元。INSTR(str,substr)返回字符串 str 中子字符串的第一个出现位置。这和LOCATE()的双参数形式相同,除非参数的顺序被颠倒。mysql> SELECT INSTR('foobarbar', 'bar'); -> 4 mysql> SELECT INSTR('xbar', 'foobar'); -> 0 这个函数支持多字节字元,并且只有当至少有一个参数是二进制字符串时区分大小写。LCASE(str)LCASE() 是 LOWER()的同义词。LEFT(str,len)返回从字符串str 开始的len 最左字符。mysql> SELECT LEFT('foobarbar', 5); -> 'fooba' LENGTH(str)返回值为字符串str 的长度,单位为字节。一个多字节字符算作多字节。这意味着 对于一个包含5个2字节字符的字符串, LENGTH() 的返回值为 10, 而 CHAR_LENGTH()的返回值则为5。mysql> SELECT LENGTH('text'); -> 4 LOAD_FILE(file_name)读取文件并将这一文件按照字符串的格式返回。 文件的位置必须在服务器上,你必须为文件制定路径全名,而且你还必须拥有FILE 特许权。文件必须可读取,文件容量必须小于 max_allowed_packet字节。若文件不存在,或因不满足上述条件而不能被读取, 则函数返回值为 NULL。mysql> UPDATE tbl_name SET blob_column=LOAD_FILE('/tmp/picture') WHERE id=1; LOCATE(substr,str) , LOCATE(substr,str,pos)第一个语法返回字符串 str中子字符串substr的第一个出现位置。第二个语法返回字符串 str中子字符串substr的第一个出现位置, 起始位置在pos。如若substr 不在str中,则返回值为0。mysql> SELECT LOCATE('bar', 'foobarbar'); -> 4 mysql> SELECT LOCATE('xbar', 'foobar'); -> 0 mysql> SELECT LOCATE('bar', 'foobarbar',5); -> 7 这个函数支持多字节字元,并且只有当至少有一个参数是二进制字符串时区分大小写。LOWER(str)返回字符串 str 以及所有根据最新的字符集映射表变为小写字母的字符 (默认为 cp1252 Latin1)。mysql> SELECT LOWER('QUADRATICALLY'); -> 'quadratically'这个函数支持多字节字元。LPAD(str,len,padstr)返回字符串 str, 其左边由字符串padstr 填补到len 字符长度。假如str 的长度大于len, 则返回值被缩短至 len 字符。mysql> SELECT LPAD('hi',4,'??'); -> '??hi' mysql> SELECT LPAD('hi',1,'??'); -> 'h' LTRIM(str)返回字符串 str ,其引导空格字符被删除。mysql> SELECT LTRIM(' barbar'); -> 'barbar' 这个函数支持多字节字元。MAKE_SET(bits,str1,str2,...)返回一个设定值 (一个包含被‘,’号分开的字字符串的字符串) ,由在bits 组中具有相应的比特的字符串组成。str1 对应比特 0, str2 对应比特1,以此类推。str1, str2, ...中的 NULL值不会被添加到结果中。mysql> SELECT MAKE_SET(1,'a','b','c'); -> 'a' mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world'); -> 'hello,world' mysql> SELECT MAKE_SET(1 | 4,'hello','nice',NULL,'world'); -> 'hello' mysql> SELECT MAKE_SET(0,'a','b','c'); -> '' MID(str,pos,len)MID(str,pos,len) 是 SUBSTRING(str,pos,len)的同义词。OCT(N)返回一个 N的八进制值的字符串表示,其中 N 是一个longlong (BIGINT)数。这等同于CONV(N,10,8)。若N 为 NULL ,则返回值为NULL。mysql> SELECT OCT(12); -> '14' OCTET_LENGTH(str)OCTET_LENGTH() 是 LENGTH()的同义词。ORD(str)若字符串str 的最左字符是一个多字节字符,则返回该字符的代码, 代码的计算通过使用以下公式计算其组成字节的数值而得出:(1st byte code)(2nd byte code × 256)(3rd byte code × 2562) ...假如最左字符不是一个多字节字符,那么 ORD()和函数ASCII()返回相同的值。mysql> SELECT ORD('2'); -> 50 POSITION(substr IN str)POSITION(substr IN str)是 LOCATE(substr,str)同义词。QUOTE(str)引证一个字符串,由此产生一个在SQL语句中可用作完全转义数据值的结果。 返回的字符串由单引号标注,每例都带有单引号 (‘'’)、 反斜线符号 (‘\’)、 ASCII NUL以及前面有反斜线符号的Control-Z 。如果自变量的值为NULL, 则返回不带单引号的单词 “NULL”。mysql> SELECT QUOTE('Don\'t!'); -> 'Don\'t!' mysql> SELECT QUOTE(NULL); -> NULL REPEAT(str,count)返回一个由重复的字符串str 组成的字符串,字符串str的数目等于count 。 若 count <= 0,则返回一个空字符串。若str 或 count 为 NULL,则返回 NULL 。mysql> SELECT REPEAT('MySQL', 3); -> 'MySQLMySQLMySQL' REPLACE(str,from_str,to_str)返回字符串str 以及所有被字符串to_str替代的字符串from_str 。mysql> SELECT REPLACE('www.shiyanlou.com', 'w', 'Ww'); -> 'WwWwWw.shiyanlou.com' 这个函数支持多字节字元。REVERSE(str)返回字符串 str ,顺序和字符顺序相反。mysql> SELECT REVERSE('abc'); -> 'cba' 这个函数支持多字节字元。RIGHT(str,len)从字符串str 开始,返回最右len 字符。mysql> SELECT RIGHT('foobarbar', 4); -> 'rbar' 这个函数支持多字节字元。RPAD(str,len,padstr)返回字符串str, 其右边被字符串 padstr填补至len 字符长度。假如字符串str 的长度大于 len,则返回值被缩短到与 len 字符相同长度。mysql> SELECT RPAD('hi',5,'?'); -> 'hi???' mysql> SELECT RPAD('hi',1,'?'); -> 'h'这个函数支持多字节字元。RTRIM(str)返回字符串 str ,结尾空格字符被删去。mysql> SELECT RTRIM('barbar '); -> 'barbar'这个函数支持多字节字元。SOUNDEX(str)从str返回一个soundex字符串。 两个具有几乎同样探测的字符串应该具有同样的 soundex 字符串。一个标准的soundex 字符串的长度为4个字符,然而SOUNDEX() 函数会返回一个人以长度的字符串。 可使用结果中的SUBSTRING() 来得到一个标准 soundex 字符串。在str中,会忽略所有未按照字母顺序排列的字符。 所有不在A-Z范围之内的国际字母符号被视为元音字母。mysql> SELECT SOUNDEX('Hello'); -> 'H400' mysql> SELECT SOUNDEX('Quadratically'); -> 'Q36324'注意:这个函数执行原始的Soundex算法,而非更加流行的加强版本(如D. Knuth所述)。其区别在于原始版本首先会删去元音,其次是重复,而加强版则首先删去重复,而后删去元音。expr1 SOUNDS LIKE expr2这相当于SOUNDEX(expr1) = SOUNDEX(expr2)。SPACE(N)返回一个由N 间隔符号组成的字符串。mysql> SELECT SPACE(6);-> ' 'SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len)不带有len 参数的格式从字符串str返回一个子字符串,起始于位置 pos。带有len参数的格式从字符串str返回一个长度同len字符相同的子字符串,起始于位置 pos。 使用 FROM的格式为标准 SQL 语法。也可能对pos使用一个负值。假若这样,则子字符串的位置起始于字符串结尾的pos 字符,而不是字符串的开头位置。在以下格式的函数中可以对pos 使用一个负值。mysql> SELECT SUBSTRING('Quadratically',5); -> 'ratically' mysql> SELECT SUBSTRING('foobarbar' FROM 4); -> 'barbar' mysql> SELECT SUBSTRING('Quadratically',5,6); -> 'ratica' mysql> SELECT SUBSTRING('Sakila', -3); -> 'ila' mysql> SELECT SUBSTRING('Sakila', -5, 3); -> 'aki' mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2); -> 'ki' 这个函数支持多字节字元。注意,如果对len使用的是一个小于1的值,则结果始终为空字符串。SUBSTR()是 SUBSTRING()的同义词。SUBSTRING_INDEX(str,delim,count)在定界符 delim 以及count 出现前,从字符串str返回自字符串。若count为正值,则返回最终定界符(从左边开始)左边的一切内容。若count为负值,则返回定界符(从右边开始)右边的一切内容。mysql> SELECT SUBSTRING_INDEX('www.shiyanlou.com', '.', 2); -> 'www.shiyanlou' mysql> SELECT SUBSTRING_INDEX('www.shiyanlou.com', '.', -2); -> 'shiyanlou.com'这个函数支持多字节字元。TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str) TRIM(remstr FROM] str)返回字符串 str , 其中所有remstr 前缀和/或后缀都已被删除。若分类符BOTH、LEADIN或TRAILING中没有一个是给定的,则假设为BOTH 。 remstr 为可选项,在未指定情况下,可删除空格。mysql> SELECT TRIM(' bar '); -> 'bar' mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx'); -> 'barxxx' mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx'); -> 'bar' mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz'); -> 'barx' 这个函数支持多字节字元。UCASE(str)UCASE()是UPPER()的同义词。UNCOMPRESS(string_to_uncompress)对经COMPRESS()函数压缩后的字符串进行解压缩。若参数为压缩值,则结果为 NULL。这个函数要求 MySQL 已被诸如zlib 之类的压缩库编译过。否则, 返回值将始终是 NULL。mysql> SELECT UNCOMPRESS(COMPRESS('any string')); -> 'any string' mysql> SELECT UNCOMPRESS('any string'); -> NULL UNCOMPRESSED_LENGTH(compressed_string)返回压缩字符串压缩前的长度。mysql> SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT('a',30)));-> 30UNHEX(str)执行从HEX(str)的反向操作。就是说,它将参数中的每一对十六进制数字理解为一个数字,并将其转化为该数字代表的字符。结果字符以二进制字符串的形式返回。mysql> SELECT UNHEX('4D7953514C'); -> 'MySQL' mysql> SELECT 0x4D7953514C; -> 'MySQL' mysql> SELECT UNHEX(HEX('string')); -> 'string' mysql> SELECT HEX(UNHEX('1267')); -> '1267' UPPER(str)返回字符串str, 以及根据最新字符集映射转化为大写字母的字符 (默认为cp1252 Latin1).mysql> SELECT UPPER('Hej'); -> 'HEJ' 该函数支持多字节字元STRCMP(expr1,expr2)若所有的字符串均相同,则返回STRCMP(),若根据当前分类次序,第一个参数小于第二个,则返回 -1,其它情况返回 1 。mysql> SELECT STRCMP('text', 'text2'); -> -1 mysql> SELECT STRCMP('text2', 'text'); -> 1 mysql> SELECT STRCMP('text', 'text'); -> 0 在执行比较时,STRCMP() 使用当前字符集。这使得默认的比较区分大小写,当操作数中的一个或两个都是二进制字符串时除外。四、数值函数4.1 算数操作符+加号:mysql> SELECT 3+5; -> 8 -减号:mysql> SELECT 3-5; -> -2 -一元减号。更换参数符号。mysql> SELECT - 2; -> -2 注意:若该 操作符同一个BIGINT同时使用,则返回值也是一个BIGINT。这意味着你应当尽量避免对可能产生–263的整数使用 –。*乘号:mysql> SELECT 3*5; -> 15 mysql> SELECT 18014398509481984*18014398509481984.0; -> 324518553658426726783156020576256.0 mysql> SELECT 18014398509481984*18014398509481984; -> 0 最后一个表达式的结果是不正确的。原因是整数相乘的结果超过了BIGINT 计算的 64比特范围。/除号:mysql> SELECT 3/5; -> 0.60 被零除的结果为 NULL:mysql> SELECT 102/(1-1); -> NULL 只有当执行的语境中,其结果要被转化为一个整数时 ,除法才会和 BIGINT 算法一起使用。DIV整数除法。 类似于 FLOOR(),然而使用BIGINT 算法也是可靠的。mysql> SELECT 5 DIV 2; -> 2 4.2 数学函数若发生错误,所有数学函数会返回 NULL 。ABS(X)返回X 的绝对值。mysql> SELECT ABS(2); -> 2 mysql> SELECT ABS(-32); -> 32 该函数支持使用BIGINT值。ACOS(X)返回X 反余弦, 即, 余弦是X的值。若X 不在-1到 1的范围之内,则返回 NULL 。mysql> SELECT ACOS(1); -> 0 mysql> SELECT ACOS(1.0001); -> NULL mysql> SELECT ACOS(0); -> 1.5707963267949 ASIN(X)返回X 的反正弦,即,正弦为X 的值。若X 若X 不在-1到 1的范围之内,则返回 NULL 。mysql> SELECT ASIN(0.2); -> 0.20135792079033 mysql> SELECT ASIN('foo'); ATAN(X)返回X 的反正切,即,正切为X 的值。mysql> SELECT ATAN(2); -> 1.1071487177941 mysql> SELECT ATAN(-2); -> -1.1071487177941 ATAN(Y,X) , ATAN2(Y,X)返回两个变量X 及Y的反正切。 它类似于 Y 或 X的反正切计算, 除非两个参数的符号均用于确定结果所在象限。mysql> SELECT ATAN(-2,2); -> -0.78539816339745 mysql> SELECT ATAN2(PI(),0); -> 1.5707963267949 CEILING(X) CEIL(X)返回不小于X 的最小整数值。mysql> SELECT CEILING(1.23); -> 2 mysql> SELECT CEIL(-1.23); -> -1 这两个函数的意义相同。注意返回值会被转化为一个BIGINT。COS(X)返回X 的余弦,其中X在弧度上已知。mysql> SELECT COS(PI()); -> -1 COT(X)返回X 的余切。mysql> SELECT COT(12); -> -1.5726734063977 mysql> SELECT COT(0); -> NULL CRC32(expr)计算循环冗余码校验值并返回一个 32比特无符号值。若参数为NULL ,则结果为 NULL。该参数应为一个字符串,而且在不是字符串的情况下会被作为字符串处理(若有可能)。mysql> SELECT CRC32('MySQL'); -> 3259397556 mysql> SELECT CRC32('mysql'); -> 2501908538 DEGREES(X)返回参数 X, 该参数由弧度被转化为度。mysql> SELECT DEGREES(PI()); -> 180 mysql> SELECT DEGREES(PI() / 2); -> 90 EXP(X)返回e的X乘方后的值(自然对数的底)。mysql> SELECT EXP(2); -> 7.3890560989307 mysql> SELECT EXP(-2); -> 0.13533528323661 mysql> SELECT EXP(0); -> 1 FLOOR(X)返回不大于X的最大整数值 。mysql> SELECT FLOOR(1.23); -> 1 mysql> SELECT FLOOR(-1.23); -> -2 注意,返回值会被转化为一个 BIGINT。FORMAT(X,D)将数字X 的格式写成'#,###,###.##'格式, 即保留小数点后 D位,而第D位的保留方式为四舍五入,然后将结果以字符串的形式返回。LN(X)返回X 的自然对数,即, X 相对于基数e 的对数。mysql> SELECT LN(2); -> 0.69314718055995 mysql> SELECT LN(-2); -> NULL 这个函数同LOG(X)具有相同意义。LOG(X) LOG(B,X)若用一个参数调用,这个函数就会返回X 的自然对数。mysql> SELECT LOG(2); -> 0.69314718055995 mysql> SELECT LOG(-2); -> NULL 若用两个参数进行调用,这个函数会返回X 对于任意基数B 的对数。mysql> SELECT LOG(2,65536); -> 16 mysql> SELECT LOG(10,100); -> 2 LOG(B,X) 就相当于 LOG(X) / LOG(B)。LOG2(X)返回X 的基数为2的对数。mysql> SELECT LOG2(65536); -> 16 mysql> SELECT LOG2(-100); -> NULL 对于查出存储一个数字需要多少个比特,LOG2()非常有效。这个函数相当于表达式 LOG(X) / LOG(2)。LOG10(X)返回X的基数为10的对数。mysql> SELECT LOG10(2); -> 0.30102999566398 mysql> SELECT LOG10(100); -> 2 mysql> SELECT LOG10(-100); -> NULL LOG10(X)相当于LOG(10,X)。MOD(N,M) , N % M N MOD M模操作。返回N 被 M除后的余数。mysql> SELECT MOD(234, 10); -> 4 mysql> SELECT 253 % 7; -> 1 mysql> SELECT MOD(29,9); -> 2 mysql> SELECT 29 MOD 9; -> 2 这个函数支持使用BIGINT 值。MOD() 对于带有小数部分的数值也起作用, 它返回除法运算后的精确余数:mysql> SELECT MOD(34.5,3); -> 1.5 PI()返回 ϖ (pi)的值。默认的显示小数位数是7位,然而 MySQL内部会使用完全双精度值。mysql> SELECT PI(); -> 3.141593 mysql> SELECT PI()+0.000000000000000000; -> 3.141592653589793116 POW(X,Y) , POWER(X,Y)返回X 的Y乘方的结果值。mysql> SELECT POW(2,2); -> 4 mysql> SELECT POW(2,-2); -> 0.25 RADIANS(X)返回由度转化为弧度的参数 X, (注意 ϖ 弧度等于180度)。mysql> SELECT RADIANS(90); -> 1.5707963267949 RAND() RAND(N)返回一个随机浮点值 v ,范围在 0 到1 之间 (即, 其范围为 0 ≤ v ≤ 1.0)。若已指定一个整数参数 N ,则它被用作种子值,用来产生重复序列。mysql> SELECT RAND(); -> 0.9233482386203 mysql> SELECT RAND(20); -> 0.15888261251047 mysql> SELECT RAND(20); -> 0.15888261251047 mysql> SELECT RAND(); -> 0.63553050033332 mysql> SELECT RAND(); -> 0.70100469486881 mysql> SELECT RAND(20); -> 0.15888261251047 若要在i ≤ R ≤ j 这个范围得到一个随机整数R ,需要用到表达式 FLOOR(i + RAND() * (j – i + 1))。例如, 若要在7 到 12 的范围(包括7和12)内得到一个随机整数, 可使用以下语句:SELECT FLOOR(7 + (RAND() * 6)); 在ORDER BY语句中,不能使用一个带有RAND()值的列,原因是 ORDER BY 会计算列的多重时间。然而,可按照如下的随机顺序检索数据行:mysql> SELECT * FROM tbl_name ORDER BY RAND(); ORDER BY RAND()同 LIMIT 的结合从一组列中选择随机样本很有用:mysql> SELECT * FROM table1, table2 WHERE a=b AND c<d -> ORDER BY RAND() LIMIT 1000; 注意,在WHERE语句中,WHERE每执行一次, RAND()就会被再计算一次。RAND()的作用不是作为一个精确的随机发生器,而是一种用来发生在同样的 MySQL版本的平台之间的可移动ad hoc随机数的快速方式。ROUND(X) ROUND(X,D)返回参数X, 其值接近于最近似的整数。在有两个参数的情况下,返回 X ,其值保留到小数点后D位,而第D位的保留方式为四舍五入。若要接保留X值小数点左边的D 位,可将 D 设为负值。mysql> SELECT ROUND(-1.23); -> -1 mysql> SELECT ROUND(-1.58); -> -2 mysql> SELECT ROUND(1.58); -> 2 mysql> SELECT ROUND(1.298, 1); -> 1.3 mysql> SELECT ROUND(1.298, 0); -> 1 mysql> SELECT ROUND(23.298, -1); -> 20 返回值的类型同 第一个自变量相同(假设它是一个整数、双精度数或小数)。这意味着对于一个整数参数,结果也是一个整数(无小数部分)。当第一个参数是十进制常数时,对于准确值参数,ROUND() 使用精密数学题库:对于准确值数字, ROUND() 使用“四舍五入” 或“舍入成最接近的数” 的规则:对于一个分数部分为 .5或大于 .5的值,正数则上舍入到邻近的整数值, 负数则下舍入临近的整数值。(换言之, 其舍入的方向是数轴上远离零的方向)。对于一个分数部分小于.5 的值,正数则下舍入下一个整数值,负数则下舍入邻近的整数值,而正数则上舍入邻近的整数值。对于近似值数字,其结果根据C 库而定。在很多系统中,这意味着 ROUND()的使用遵循“舍入成最接近的偶数”的规则: 一个带有任何小数部分的值会被舍入成最接近的偶数整数。以下举例说明舍入法对于精确值和近似值的不同之处:mysql> SELECT ROUND(2.5), ROUND(25E-1); SIGN(X)返回参数作为-1、 0或1的符号,该符号取决于X 的值为负、零或正。mysql> SELECT SIGN(-32); -> -1 mysql> SELECT SIGN(0); -> 0 mysql> SELECT SIGN(234); -> 1 SIN(X)返回X 正弦,其中 X 在弧度中被给定。mysql> SELECT SIN(PI()); -> 1.2246063538224e-16 mysql> SELECT ROUND(SIN(PI())); -> 0 SQRT(X)返回非负数X 的二次方根。mysql> SELECT SQRT(4); -> 2 mysql> SELECT SQRT(20); -> 4.4721359549996 mysql> SELECT SQRT(-16); -> NULL TAN(X)返回X 的正切,其中X 在弧度中被给定。mysql> SELECT TAN(PI()); -> -1.2246063538224e-16 mysql> SELECT TAN(PI()+1); -> 1.5574077246549 TRUNCATE(X,D)返回被舍去至小数点后D位的数字X。若D 的值为 0, 则结果不带有小数点或不带有小数部分。可以将D设为负数,若要截去(归零) X小数点左起第D位开始后面所有低位的值.mysql> SELECT TRUNCATE(1.223,1); -> 1.2 mysql> SELECT TRUNCATE(1.999,1); -> 1.9 mysql> SELECT TRUNCATE(1.999,0); -> 1 mysql> SELECT TRUNCATE(-1.999,1); -> -1.9 mysql> SELECT TRUNCATE(122,-2); -> 100 mysql> SELECT TRUNCATE(10.28*100,0); -> 1028 所有数字的舍入方向都接近于零。五、日期和时间函数ADDDATE(date,INTERVAL expr type) ADDDATE(expr,days)当被第二个参数的INTERVAL格式激活后, ADDDATE()就是DATE_ADD()的同义词。相关函数SUBDATE() 则是DATE_SUB()的同义词。mysql> SELECT DATE_ADD('1998-01-02', INTERVAL 31 DAY); -> '1998-02-02' mysql> SELECT ADDDATE('1998-01-02', INTERVAL 31 DAY); -> '1998-02-02'¨NBSP;若 days 参数只是整数值,则 MySQL 5.1将其作为天数值添加至 expr。mysql> SELECT ADDDATE('1998-01-02', 31); -> '1998-02-02'ADDTIME(expr,expr2)ADDTIME()将 expr2添加至expr 然后返回结果。 expr 是一个时间或时间日期表达式,而expr2 是一个时间表达式。mysql> SELECT ADDTIME('1997-12-31 23:59:59.999999', -> '1 1:1:1.000002'); -> '1998-01-02 01:01:01.000001' mysql> SELECT ADDTIME('01:00:00.999999', '02:00:00.999998'); -> '03:00:01.999997'CONVERT_TZ(dt,from_tz,to_tz)CONVERT_TZ() 将时间日期值dt 从from_tz 给出的时区转到to_tz给出的时区,然后返回结果值。在从若from_tz 到UTC的转化过程中,该值超出 TIMESTAMP 类型的被支持范围,那么转化不会发生。mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET'); -> '2004-01-01 13:00:00' mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00'); -> '2004-01-01 22:00:00'注释:若要使用诸如 'MET'或 'Europe/Moscow'之类的指定时间区,首先要设置正确的时区表。CURDATE()将当前日期按照'YYYY-MM-DD' 或YYYYMMDD 格式的值返回,具体格式根据函数用在字符串或是数字语境中而定。mysql> SELECT CURDATE(); -> '1997-12-15' mysql> SELECT CURDATE() + 0; -> 19971215CURRENT_DATE CURRENT_DATE()CURRENT_DATE和CURRENT_DATE()是的同义词.CURTIME()将当前时间以'HH:MM:SS'或 HHMMSS 的格式返回, 具体格式根据函数用在字符串或是数字语境中而定。mysql> SELECT CURTIME(); -> '23:50:26' mysql> SELECT CURTIME() + 0; -> 235026CURRENT_TIME, CURRENT_TIME()CURRENT_TIME 和CURRENT_TIME() 是CURTIME()的同义词。CURRENT_TIMESTAMP, CURRENT_TIMESTAMP()CURRENT_TIMESTAMP和 CURRENT_TIMESTAMP()是NOW()的同义词。DATE(expr)提取日期或时间日期表达式expr中的日期部分。mysql> SELECT DATE('2014-10-29 01:02:03'); -> '2014-10-29'DATEDIFF(expr,expr2)DATEDIFF() 返回起始时间 expr和结束时间expr2之间的天数。Expr和expr2 为日期或 date-and-time 表达式。计算中只用到这些值的日期部分。mysql> SELECT DATEDIFF('1997-12-31 23:59:59','1997-12-30'); -> 1 mysql> SELECT DATEDIFF('1997-11-30 23:59:59','1997-12-31'); -> -31DATE_ADD(date,INTERVAL expr type) DATE_SUB(date,INTERVAL expr type)这些函数执行日期运算。 date 是一个 DATETIME 或DATE值,用来指定起始时间。 expr 是一个表达式,用来指定从起始日期添加或减去的时间间隔值。 Expr是一个字符串;对于负值的时间间隔,它可以以一个 ‘-’开头。 type 为关键词,它指示了表达式被解释的方式。关键词INTERVA及 type 分类符均不区分大小写。以下表显示了type 和expr 参数的关系:MySQL 允许任何expr 格式中的标点分隔符。表中所显示的是建议的 分隔符。若 date 参数是一个 DATE 值,而你的计算只会包括 YEAR、MONTH和DAY部分(即, 没有时间部分), 其结果是一个DATE 值。否则,结果将是一个 DATETIME值。若位于另一端的表达式是一个日期或日期时间值 , 则INTERVAL expr type只允许在 + 操作符的两端。对于 –操作符, INTERVAL expr type 只允许在其右端,原因是从一个时间间隔中提取一个日期或日期时间值是毫无意义的。 (见下面的例子)。mysql> SELECT '1997-12-31 23:59:59' + INTERVAL 1 SECOND; -> '1998-01-01 00:00:00' mysql> SELECT INTERVAL 1 DAY + '1997-12-31'; -> '1998-01-01' mysql> SELECT '1998-01-01' - INTERVAL 1 SECOND; -> '1997-12-31 23:59:59' mysql> SELECT DATE_ADD('1997-12-31 23:59:59', -> INTERVAL 1 SECOND); -> '1998-01-01 00:00:00' mysql> SELECT DATE_ADD('1997-12-31 23:59:59', -> INTERVAL 1 DAY); -> '1998-01-01 23:59:59' mysql> SELECT DATE_ADD('1997-12-31 23:59:59', -> INTERVAL '1:1' MINUTE_SECOND); -> '1998-01-01 00:01:00' mysql> SELECT DATE_SUB('1998-01-01 00:00:00', -> INTERVAL '1 1:1:1' DAY_SECOND); -> '1997-12-30 22:58:59' mysql> SELECT DATE_ADD('1998-01-01 00:00:00', -> INTERVAL '-1 10' DAY_HOUR); -> '1997-12-30 14:00:00' mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY); -> '1997-12-02' mysql> SELECT DATE_ADD('1992-12-31 23:59:59.000002', -> INTERVAL '1.999999' SECOND_MICROSECOND); -> '1993-01-01 00:00:01.000001'若你指定了一个过于短的时间间隔值 (不包括type 关键词所预期的所有时间间隔部分), MySQL 假定你已经省去了时间间隔值的最左部分。 例如,你指定了一种类型的DAY_SECOND, expr 的值预期应当具有天、 小时、分钟和秒部分。若你指定了一个类似 '1:10'的值, MySQL 假定天和小时部分不存在,那么这个值代表分和秒。换言之, '1:10' DAY_SECOND 被解释为相当于 '1:10' MINUTE_SECOND。这相当于 MySQL将TIME 值解释为所耗费的时间而不是日时的解释方式。假如你对一个日期值添加或减去一些含有时间部分的内容,则结果自动转化为一个日期时间值:mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 DAY); -> '1999-01-02' mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 HOUR); -> '1999-01-01 01:00:00'假如你使用了格式严重错误的日期,则结果为 NULL。假如你添加了 MONTH、YEAR_MONTH或YEAR ,而结果日期中有一天的日期大于添加的月份的日期最大限度,则这个日期自动被调整为添加月份的最大日期:mysql> SELECT DATE_ADD('1998-01-30', INTERVAL 1 MONTH); -> '1998-02-28'DATE_FORMAT(date,format)根据format 字符串安排date 值的格式。以下说明符可用在 format 字符串中:所有其它字符都被复制到结果中,无需作出解释。注意, ‘%’字符要求在格式指定符之前。月份和日期说明符的范围从零开始,原因是 MySQL允许存储诸如 '2004-00-00'的不完全日期.mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y'); -> 'Saturday October 1997' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s'); -> '22:23:00' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%D %y %a %d %m %b %j'); -> '4th 97 Sat 04 10 Oct 277' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H %k %I %r %T %S %w'); -> '22 22 10 10:23:00 PM 22:23:00 00 6' mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V'); -> '1998 52'DAY(date)DAY() 和DAYOFMONTH()的意义相同。DAYNAME(date)返回date 对应的工作日名称。mysql> SELECT DAYNAME('1998-02-05'); -> '周四'DAYOFMONTH(date)返回date 对应的该月日期,范围是从 1到31。mysql> SELECT DAYOFMONTH('1998-02-03'); -> 3DAYOFWEEK(date)返回date (1 = 周日, 2 = 周一, ..., 7 = 周六)对应的工作日索引。这些索引值符合 ODBC标准。mysql> SELECT DAYOFWEEK('1998-02-03'); -> 3DAYOFYEAR(date)返回date 对应的一年中的天数,范围是从 1到366。mysql> SELECT DAYOFYEAR('1998-02-03'); -> 34EXTRACT(type FROM date)EXTRACT()函数所使用的时间间隔类型说明符同 DATE_ADD()或DATE_SUB()的相同,但它从日期中提取其部分,而不是执行日期运算。mysql> SELECT EXTRACT(YEAR FROM '1999-07-02'); -> 1999 mysql> SELECT EXTRACT(YEAR_MONTH FROM '1999-07-02 01:02:03'); -> 199907 mysql> SELECT EXTRACT(DAY_MINUTE FROM '1999-07-02 01:02:03'); -> 20102 mysql> SELECT EXTRACT(MICROSECOND -> FROM '2003-01-02 10:30:00.00123'); -> 123FROM_DAYS(N)给定一个天数 N, 返回一个DATE值。mysql> SELECT FROM_DAYS(729669); -> '1997-10-07'使用 FROM_DAYS()处理古老日期时,务必谨慎。他不用于处理阳历出现前的日期(1582)FROM_UNIXTIME(unix_timestamp) , FROM_UNIXTIME(unix_timestamp,format)返回'YYYY-MM-DD HH:MM:SS'或YYYYMMDDHHMMSS 格式值的unix_timestamp参数表示,具体格式取决于该函数是否用在字符串中或是数字语境中。若format 已经给出,则结果的格式是根据format 字符串而定。 format 可以包含同DATE_FORMAT() 函数输入项列表中相同的说明符。mysql> SELECT FROM_UNIXTIME(875996580); -> '1997-10-04 22:23:00' mysql> SELECT FROM_UNIXTIME(875996580) + 0; -> 19971004222300 mysql> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(), -> '%Y %D %M %h:%i:%s %x'); -> '2003 6th August 06:22:58 2003'GET_FORMAT(DATE|TIME|DATETIME, 'EUR'|'USA'|'JIS'|'ISO'|'INTERNAL')返回一个格式字符串。这个函数在同DATE_FORMAT() 及STR_TO_DATE()函数结合时很有用。第一个参数的3个可能值和第二个参数的5个可能值产生 15 个可能格式字符串 (对于使用的说明符,请参见DATE_FORMAT()函数说明表 )。ISO 格式为ISO 9075, 而非ISO 8601.也可以使用TIMESTAMP, 这时GET_FORMAT()的返回值和DATETIME相同。mysql> SELECT DATE_FORMAT('2003-10-03',GET_FORMAT(DATE,'EUR')); -> '03.10.2003' mysql> SELECT STR_TO_DATE('10.31.2003',GET_FORMAT(DATE,'USA')); -> '2003-10-31'HOUR(time)返回time 对应的小时数。对于日时值的返回值范围是从 0 到 23 。mysql> SELECT HOUR('10:05:03'); -> 10然而, TIME 值的范围实际上非常大, 所以HOUR可以返回大于23的值。mysql> SELECT HOUR('272:59:59'); -> 272LAST_DAY(date)获取一个日期或日期时间值,返回该月最后一天对应的值。若参数无效,则返回NULL。mysql> SELECT LAST_DAY('2003-02-05'); -> '2003-02-28' mysql> SELECT LAST_DAY('2004-02-05'); -> '2004-02-29' mysql> SELECT LAST_DAY('2004-01-01 01:01:01'); -> '2004-01-31' mysql> SELECT LAST_DAY('2003-03-32'); -> NULLLOCALTIME, LOCALTIME()LOCALTIME 及 LOCALTIME()和NOW()具有相同意义。LOCALTIMESTAMP, LOCALTIMESTAMP()LOCALTIMESTAMP和LOCALTIMESTAMP()和NOW()具有相同意义。MAKEDATE(year,dayofyear)给出年份值和一年中的天数值,返回一个日期。dayofyear 必须大于 0 ,否则结果为 NULL。mysql> SELECT MAKEDATE(2001,31), MAKEDATE(2001,32); -> '2001-01-31', '2001-02-01' mysql> SELECT MAKEDATE(2001,365), MAKEDATE(2004,365); -> '2001-12-31', '2004-12-30' mysql> SELECT MAKEDATE(2001,0); -> NULLMAKETIME(hour,minute,second)返回由hour、 minute和second 参数计算得出的时间值。mysql> SELECT MAKETIME(12,15,30); -> '12:15:30'MICROSECOND(expr)从时间或日期时间表达式expr返回微秒值,其数字范围从 0到 999999。mysql> SELECT MICROSECOND('12:00:00.123456'); -> 123456 mysql> SELECT MICROSECOND('1997-12-31 23:59:59.000010'); -> 10MINUTE(time)返回 time 对应的分钟数,范围是从 0 到 59。mysql> SELECT MINUTE('98-02-03 10:05:03'); -> 5MONTH(date)返回date 对应的月份,范围时从 1 到 12。mysql> SELECT MONTH('1998-02-03'); -> 2MONTHNAME(date)返回date 对应月份的全名。mysql> SELECT MONTHNAME('1998-02-05'); -> 'February 'NOW()返回当前日期和时间值,其格式为 'YYYY-MM-DD HH:MM:SS' 或YYYYMMDDHHMMSS , 具体格式取决于该函数是否用在字符串中或数字语境中。mysql> SELECT NOW(); -> '1997-12-15 23:50:26' mysql> SELECT NOW() + 0; -> 19971215235026在一个存储程序或触发器内, NOW() 返回一个常数时间,该常数指示了该程序或触发语句开始执行的时间。这同SYSDATE()的运行有所不同。PERIOD_ADD(P,N)添加 N 个月至周期P (格式为YYMM 或YYYYMM),返回值的格式为 YYYYMM。注意周期参数 P 不是日期值。mysql> SELECT PERIOD_ADD(9801,2); -> 199803PERIOD_DIFF(P1,P2)返回周期P1和 P2 之间的月份数。P1 和P2 的格式应该为YYMM或YYYYMM。注意周期参数 P1和P2 不是日期值。mysql> SELECT PERIOD_DIFF(9802,199703); -> 11QUARTER(date)返回date 对应的一年中的季度值,范围是从 1到 4。mysql> SELECT QUARTER('98-04-01'); -> 2SECOND(time)返回time 对应的秒数, 范围是从 0到59。mysql> SELECT SECOND('10:05:03'); -> 3SEC_TO_TIME(seconds)返回被转化为小时、 分钟和秒数的seconds参数值, 其格式为 'HH:MM:SS' 或HHMMSS,具体格式根据该函数是否用在字符串或数字语境中而定。mysql> SELECT SEC_TO_TIME(2378); -> '00:39:38' mysql> SELECT SEC_TO_TIME(2378) + 0; -> 3938STR_TO_DATE(str,format)这是DATE_FORMAT() 函数的倒转。它获取一个字符串 str 和一个格式字符串format。若格式字符串包含日期和时间部分,则 STR_TO_DATE()返回一个 DATETIME 值, 若该字符串只包含日期部分或时间部分,则返回一个 DATE 或TIME值。str所包含的日期、时间或日期时间值应该在format指示的格式中被给定。对于可用在format中的说明符,请参见DATE_FORMAT() 函数说明表。 所有其它的字符被逐字获取,因此不会被解释。若 str 包含一个非法日期、时间或日期时间值,则 STR_TO_DATE()返回NULL。同时,一个非法值会引起警告。对日期值部分的范围检查在11.3.1节,“DATETIME、DATE和TIMESTAMP类型”有详细说明。其意义是,例如, 只要具体日期部分的范围时从 1到 31之间,则允许一个日期中的具体日期部分大于一个月中天数值。并且,允许“零”日期或带有0值部分的日期。mysql> SELECT STR_TO_DATE('00/00/0000', '%m/%d/%Y'); -> '0000-00-00' mysql> SELECT STR_TO_DATE('04/31/2004', '%m/%d/%Y'); -> '2004-04-31'SUBDATE(date,INTERVAL expr type) SUBDATE(expr,days)当被第二个参数的 INTERVAL型式调用时, SUBDATE()和DATE_SUB()的意义相同。mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY); -> '1997-12-02' mysql> SELECT SUBDATE('1998-01-02', INTERVAL 31 DAY); -> '1997-12-02'第二个形式允许对days使用整数值。在这些情况下,它被算作由日期或日期时间表达式 expr中提取的天数。mysql> SELECT SUBDATE('1998-01-02 12:00:00', 31); -> '1997-12-02 12:00:00'注意不能使用格式 "%X%V" 来将一个 year-week 字符串转化为一个日期,原因是当一个星期跨越一个月份界限时,一个年和星期的组合不能标示一个唯一的年和月份。若要将year-week转化为一个日期,则也应指定具体工作日:mysql> select str_to_date('200442 Monday', '%X%V %W'); -> 2004-10-18SUBTIME(expr,expr2)SUBTIME()从expr 中提取expr2 ,然后返回结果。expr 是一个时间或日期时间表达式,而xpr2 是一个时间表达式。mysql> SELECT SUBTIME('1997-12-31 23:59:59.999999','1 1:1:1.000002'); -> '1997-12-30 22:58:58.999997' mysql> SELECT SUBTIME('01:00:00.999999', '02:00:00.999998'); -> '-00:59:59.999999'SYSDATE()返回当前日期和时间值,格式为'YYYY-MM-DD HH:MM:SS' 或YYYYMMDDHHMMSS, 具体格式根据函数是否用在字符串或数字语境而定。在一个存储程序或触发器中, SYSDATE()返回其执行的时间, 而非存储或触发语句开始执行的时间。这个NOW()的运作有所不同。TIME(expr)提取一个时间或日期时间表达式的时间部分,并将其以字符串形式返回。mysql> SELECT TIME('2003-12-31 01:02:03'); -> '01:02:03' mysql> SELECT TIME('2003-12-31 01:02:03.000123'); -> '01:02:03.000123'TIMEDIFF(expr,expr2)TIMEDIFF() 返回起始时间 expr 和结束时间expr2 之间的时间。 expr 和expr2 为时间或 date-and-time 表达式,两个的类型必须一样。mysql> SELECT TIMEDIFF('2000:01:01 00:00:00', -> '2000:01:01 00:00:00.000001'); -> '-00:00:00.000001' mysql> SELECT TIMEDIFF('1997-12-31 23:59:59.000001', -> '1997-12-30 01:01:01.000002'); -> '46:58:57.999999'TIMESTAMP(expr) , TIMESTAMP(expr,expr2)对于一个单参数,该函数将日期或日期时间表达式 expr 作为日期时间值返回.对于两个参数, 它将时间表达式 expr2 添加到日期或日期时间表达式 expr 中,将theresult作为日期时间值返回。mysql> SELECT TIMESTAMP('2003-12-31'); -> '2003-12-31 00:00:00' mysql> SELECT TIMESTAMP('2003-12-31 12:00:00','12:00:00'); -> '2004-01-01 00:00:00'TIMESTAMPADD(interval,intexpr,datetime_expr)将整型表达式int_expr 添加到日期或日期时间表达式 datetime_expr中。 int_expr 的单位被时间间隔参数给定,该参数必须是以下值的其中一个: FRAC_SECOND、SECOND、 MINUTE、 HOUR、 DAY、 WEEK、 MONTH、 QUARTER或 YEAR。可使用所显示的关键词指定Interval值,或使用SQL_TSI前缀。例如, DAY或SQL_TSI_DAY 都是正确的。mysql> SELECT TIMESTAMPADD(MINUTE,1,'2003-01-02'); -> '2003-01-02 00:01:00' mysql> SELECT TIMESTAMPADD(WEEK,1,'2003-01-02'); -> '2003-01-09'TIMESTAMPDIFF(interval,datetime_expr1,datetime_expr2)返回日期或日期时间表达式datetime_expr1 和datetime_expr2the 之间的整数差。其结果的单位由interval 参数给出。interval 的法定值同TIMESTAMPADD()函数说明中所列出的相同。mysql> SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01'); -> 3 mysql> SELECT TIMESTAMPDIFF(YEAR,'2002-05-01','2001-01-01'); -> -1TIME_FORMAT(time,format)其使用和 DATE_FORMAT()函数相同, 然而format 字符串可能仅会包含处理小时、分钟和秒的格式说明符。其它说明符产生一个NULL值或0。若time value包含一个大于23的小时部分,则 %H 和 %k 小时格式说明符会产生一个大于0..23的通常范围的值。另一个小时格式说明符产生小时值模数12。mysql> SELECT TIME_FORMAT('100:00:00', '%H %k %h %I %l'); -> '100 100 04 04 4'TIME_TO_SEC(time)返回已转化为秒的time参数。mysql> SELECT TIME_TO_SEC('22:23:00'); -> 80580 mysql> SELECT TIME_TO_SEC('00:39:38'); -> 2378TO_DAYS(date)给定一个日期date, 返回一个天数 (从年份0开始的天数 )。mysql> SELECT TO_DAYS(950501); -> 728779 mysql> SELECT TO_DAYS('1997-10-07'); -> 729669TO_DAYS() 不用于阳历出现(1582)前的值,原因是当日历改变时,遗失的日期不会被考虑在内。UNIX_TIMESTAMP(), UNIX_TIMESTAMP(date)若无参数调用,则返回一个Unix timestamp ('1970-01-01 00:00:00' GMT 之后的秒数) 作为无符号整数。若用date 来调用UNIX_TIMESTAMP(),它会将参数值以'1970-01-01 00:00:00' GMT后的秒数的形式返回。date 可以是一个DATE 字符串、一个 DATETIME字符串、一个 TIMESTAMP或一个当地时间的YYMMDD 或YYYMMDD格式的数字。mysql> SELECT UNIX_TIMESTAMP(); -> 882226357 mysql> SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00'); -> 875996580当 UNIX_TIMESTAMP被用在 TIMESTAMP列时, 函数直接返回内部时戳值, 而不进行任何隐含的 “string-to-Unix-timestamp”转化。假如你向UNIX_TIMESTAMP()传递一个溢出日期,它会返回 0,但请注意只有基本范围检查会被履行 (年份从1970 到 2037, 月份从01到12,日期从 01 到31)。UTC_DATE, UTC_DATE()返回当前 UTC日期值,其格式为 'YYYY-MM-DD' 或 YYYYMMDD,具体格式取决于函数是否用在字符串或数字语境中。mysql> SELECT UTC_DATE(), UTC_DATE() + 0; -> '2014-10-29', 20141029UTC_TIME, UTC_TIME()返回当前 UTC 值,其格式为 'HH:MM:SS' 或HHMMSS,具体格式根据该函数是否用在字符串或数字语境而定。mysql> SELECT UTC_TIME(), UTC_TIME() + 0; -> '18:07:53', 180753UTC_TIMESTAMP, UTC_TIMESTAMP()返回当前UTC日期及时间值,格式为 'YYYY-MM-DD HH:MM:SS' 或YYYYMMDDHHMMSS,具体格式根据该函数是否用在字符串或数字语境而定。mysql> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0; -> '2003-08-14 18:08:04', 20030814180804WEEK(date[,mode])该函数返回date 对应的星期数。WEEK() 的双参数形式允许你指定该星期是否起始于周日或周一, 以及返回值的范围是否为从0 到53 或从1 到53。若 mode参数被省略,则使用default_week_format系统自变量的值。请参见5.3.3节,“服务器系统变量”。以下表说明了mode 参数的工作过程:mysql> SELECT WEEK('1998-02-20'); -> 7 mysql> SELECT WEEK('1998-02-20',0); -> 7 mysql> SELECT WEEK('1998-02-20',1); -> 8 mysql> SELECT WEEK('1998-12-31',1); -> 53注意,假如有一个日期位于前一年的最后一周, 若你不使用2、3、6或7作为mode 参数选择,则MySQL返回 0:mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0); -> 2000, 0有人或许会提出意见,认为 MySQL 对于WEEK() 函数应该返回 52 ,原因是给定的日期实际上发生在1999年的第52周。我们决定返回0作为代替的原因是我们希望该函数能返回“给定年份的星期数”。这使得WEEK() 函数在同其它从日期中抽取日期部分的函数结合时的使用更加可靠。假如你更希望所计算的关于年份的结果包括给定日期所在周的第一天,则应使用 0、2、5或 7 作为mode参数选择。mysql> SELECT WEEK('2000-01-01',2); -> 52作为选择,可使用 YEARWEEK()函数:mysql> SELECT YEARWEEK('2000-01-01'); -> 199952 mysql> SELECT MID(YEARWEEK('2000-01-01'),5,2); -> '52'WEEKDAY(date)返回date (0 = 周一, 1 = 周二, ... 6 = 周日)对应的工作日索引 weekday index formysql> SELECT WEEKDAY('1998-02-03 22:23:00'); -> 1 mysql> SELECT WEEKDAY('1997-11-05'); -> 2WEEKOFYEAR(date)将该日期的阳历周以数字形式返回,范围是从1到53。它是一个兼容度函数,相当于WEEK(date,3)。mysql> SELECT WEEKOFYEAR('1998-02-20'); -> 8YEAR(date)返回date 对应的年份,范围是从1000到9999。mysql> SELECT YEAR('98-02-03'); -> 1998YEARWEEK(date), YEARWEEK(date,start)返回一个日期对应的年或周。start参数的工作同 start参数对 WEEK()的工作相同。结果中的年份可以和该年的第一周和最后一周对应的日期参数有所不同。mysql> SELECT YEARWEEK('1987-01-01'); -> 198653注意,周数和WEEK()函数队可选参数0或 1可能会返回的(0) w有所不同,原因是此时 WEEK() 返回给定年份的语境中的周。六、全文搜索功能MATCH (col1,col2,...) AGAINST (expr [IN BOOLEAN MODE | WITH QUERY EXPANSION])mysql支持全文索引和搜索功能。MySQL中的全文索引类型FULLTEXT的索引。 FULLTEXT 索引仅可用于 MyISAM 表;他们可以从CHAR、 VARCHAR或TEXT列中作为CREATE TABLE语句的一部分被创建,或是随后使用ALTER TABLE 或 CREATE INDEX被添加。对于较大的数据集,将你的资料输入一个没有FULLTEXT索引的表中,然后创建索引, 其速度比把资料输入现有FULLTEXT索引的速度更为快。mysql> CREATE TABLE articles ( -> id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, -> title VARCHAR(200), -> body TEXT, -> FULLTEXT (title,body) -> );mysql> INSERT INTO articles (title,body) VALUES -> ('MySQL Tutorial','DBMS stands for DataBase ...'), -> ('How To Use MySQL Well','After you went through a ...'), -> ('Optimizing MySQL','In this tutorial we will show ...'), -> ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), -> ('MySQL vs. YourSQL','In the following database comparison ...'), -> ('MySQL Security','When configured properly, MySQL ...');mysql> SELECT * FROM articles -> WHERE MATCH (title,body) AGAINST ('database');mysql> SELECT id, MATCH (title,body) AGAINST ('Tutorial') -> FROM articles;mysql> SELECT id, body, MATCH (title,body) AGAINST -> ('Security implications of running MySQL as root') AS score -> FROM articles WHERE MATCH (title,body) AGAINST -> ('Security implications of running MySQL as root');mysql> SELECT * FROM articles -> WHERE MATCH (title,body) AGAINST ('MySQL');七、Cast函数和操作符BINARY BINARY操作符将后面的字符串抛给一个二进制字符串。这是一种简单的方式来促使逐字节而不是逐字符的进行列比较。这使得比较区分大小写,即使该列不被定义为 BINARY或 BLOB。BINARY也会产生结尾空白,从而更加显眼。mysql> SELECT 'a' = 'A'; -> 1 mysql> SELECT BINARY 'a' = 'A'; -> 0 mysql> SELECT 'a' = 'a '; -> 1 mysql> SELECT BINARY 'a' = 'a '; -> 0BINARY影响整个比较;它可以在任何操作数前被给定,而产生相同的结果。BINARY str 是CAST(str AS BINARY)的缩略形式。注意,在一些语境中,假如你将一个编入索引的列派给BINARY, MySQL 将不能有效使用这个索引。假如你想要将一个 BLOB值或其它二进制字符串进行区分大小写的比较,你可利用二进制字符串没有字符集这一事实实现这个目的,这样就不会有文书夹的概念。为执行一个区分大小写的比较,可使用 CONVERT()函数将一个字符串值转化为一个不区分大小写的字符集。其结果为一个非二进制字符串,因此 LIKE 操作也不会区分大小写:SELECT 'A' LIKE CONVERT(blob_col USING latin1) FROM tbl_name;若要使用一个不同的字符集, 替换其在上述语句中的latin1名。CONVERT()一般可用于比较出现在不同字符集中的字符串。CAST(expr AS type), CONVERT(expr,type) , CONVERT(expr USING transcoding_name)CAST()和CONVERT() 函数可用来获取一个类型的值,并产生另一个类型的值。这个类型可以是以下值其中的一个:BINARY[(N)]CHAR[(N)]DATEDATETIMEDECIMALSIGNED [INTEGER]TIMEUNSIGNED [INTEGER]BINARY 产生一个二进制字符串。假如给定了随意长度N,则 BINARY[N] 使 cast使用该参数的不多于 N 个字节。同样的, CHAR[N]会使 cast 使用该参数的不多于N 个字符。CAST() and CONVERT(... USING ...) 是标准 SQL语法。CONVERT()的非USING 格式是ofis ODBC语法。带有USING的CONVERT() 被用来在不同的字符集之间转化数据。在 MySQL中, 自动译码名和相应的字符集名称相同。例如。 这个语句将服务器的默认字符集中的字符串 'abc'转化为utf8字符集中相应的字符串:SELECT CONVERT('abc' USING utf8);当你想要在一个CREATE ... SELECT 语句中创建一个特殊类型的列,则cast函数会很有用:CREATE TABLE new_table SELECT CAST('2000-01-01' AS DATE);该函数也用于ENUM 列按词法顺序的排序。通常ENUM列的排序在使用内部数值时发生。将这些值按照词法顺序派给 CHAR 结果:SELECT enum_col FROM tbl_name ORDER BY CAST(enum_col AS CHAR);CAST(str AS BINARY)和BINARY str相同。 CAST(expr AS CHAR) 将表达式视为一个带有默认字符集的字符串。若用于一个诸如 CONCAT('Date: ',CAST(NOW() AS DATE))这样的比较复杂的表达式的一部分,CAST()也会改变结果。你不应在不同的格式中使用 CAST() 来析取数据,但可以使用诸如LEFT() 或 EXTRACT() 的样的字符串函数来代替。若要在数值语境中将一个字符串派给一个数值, 通常情况下,除了将字符串值作为数字使用外,你不需要做任何事:mysql> SELECT 1+'1'; -> 2若要在一个字符串语境中使用一个数字,该数字会被自动转化为一个BINARY 字符串。mysql> SELECT CONCAT('hello you ',2); -> 'hello you 2'mysql 支持带符号和无符号的64比特值的运算。若你正在使用数字操作符 (如 +) 而其中一个操作数为无符号整数,则结果为无符号。可使用SIGNED 和UNSIGNED cast 操作符来覆盖它。将运算分别派给带符号或无符号64比特整数。mysql> SELECT CAST(1-2 AS UNSIGNED) -> 18446744073709551615 mysql> SELECT CAST(CAST(1-2 AS UNSIGNED) AS SIGNED); -> -1注意,假如任意一个操作数为一个浮点值,则结果为一个浮点值, 且不会受到上述规则影响 (关于这一点, DECIMAL 列值被视为浮点值)。mysql> SELECT CAST(1 AS UNSIGNED) - 2.0; -> -1.0若你在一个算术运算中使用了一个字符串,它会被转化为一个浮点数。八、其他函数8.1 位函数对于比特运算,MySQL 使用 BIGINT (64比特) 算法,因此这些操作符的最大范围是 64 比特。|Bitwise OR:mysql> SELECT 29 | 15; -> 31其结果为一个64比特无符号整数。&Bitwise AND:mysql> SELECT 29 & 15; -> 13其结果为一个64比特无符号整数。^Bitwise XOR:mysql> SELECT 1 ^ 1; -> 0 mysql> SELECT 1 ^ 0; -> 1 mysql> SELECT 11 ^ 3; -> 8结果为一个64比特无符号整数。<<把一个longlong (BIGINT)数左移两位。mysql> SELECT 1 << 2; -> 4其结果为一个64比特无符号整数。> >把一个longlong (BIGINT)数右移两位。mysql> SELECT 4 >> 2; -> 1其结果为一个64比特无符号整数。~反转所有比特。mysql> SELECT 5 & ~1; -> 4其结果为一个64比特无符号整数。BIT_COUNT(N)返回参数N 中所设置的比特数mysql> SELECT BIT_COUNT(29); -> 48.2 加密函数本节介绍了加密和加密值。若你想要储存一些由可能包含任意字节值的加密函数返回的结果,使用BLOB列而不是 CHAR 或VARCHAR 列,从而避免由于结尾空格的删除而改变一些数据值的潜在问题。AES_ENCRYPT(str,key_str) , AES_DECRYPT(crypt_str,key_str)这些函数允许使用官方AES进行加密和数据加密 (高级加密标准 ) 算法, 即以前人们所熟知的 “Rijndael”。 保密关键字的长度为128比特,不过你可以通过改变源而将其延长到 256 比特。我们选择了 128比特的原因是它的速度要快得多,且对于大多数用途而言这个保密程度已经够用。输入参数可以为任何长度。若任何一个参数为NULL,则函数的结果也是NULL。因为 AES 是块级算法,使用填充将不均衡长度字符串编码,这样结果字符串的长度的算法为 16 * (trunc(string_length / 16) + 1)。若 AES_DECRYPT()检测到无效数据或不正确填充,它会返回 NULL。然而,若输入的资料或密码无效时, AES_DECRYPT()有可能返回一个非 NULL 值 (可能为无用信息 )。AES_ENCRYPT()和AES_DECRYPT() 可以被看作MySQL中普遍通用的密码最安全的加密函数。DECODE(crypt_str,pass_str)使用 pass_str 作为密码,解密加密字符串 crypt_str, crypt_str 应该是由ENCODE()返回的字符串。ENCODE(str,pass_str)使用pass_str 作为密码,解密 str 。 使用DECODE()解密结果。结果是一个和str长度相同的二进制字符串。若你想要将其保留在一个列中,可使用 BLOB 列类型。DES_DECRYPT(crypt_str[,key_str])使用DES_ENCRYPT()加密一个字符串。若出现错误,这个函数会返回 NULL。注意,这个函数只有当MySQL在SSL 的支持下配置完毕时才会运作。假如没有给定 key_str 参数, DES_DECRYPT() 会首先检查加密字符串的第一个字节, 从而确定用来加密原始字符串的DES密码关键字数字,之后从DES关键字文件中读取关键字从而解密信息。为使其运行,用户必须享有 SUPER 特权。可以选择--des-key-file服务器指定关键字文件。假如你向这个函数传递一个key_str 参数,该字符串被用作解密信息的关键字。若 crypt_str 参数看起来不是一个加密字符串, MySQL 会返回给定的 crypt_str。DES_ENCRYPT(str[,(key_num|key_str)])用Triple-DES 算法给出的关键字加密字符串。若出现错误,这个函数会返回NULL。注意,这个函数只有当MySQL 在SSL的支持下配置完毕后才会运行。请参见5.8.7节,“使用安全连接”.使用的加密关键字的选择基于第二个到 DES_ENCRYPT()的参数,假如给定:选择--des-key-file服务器指定关键字文件。返回字符串是一个二进制字符串,其中第一个字符为 CHAR(128 | key_num)。加上 128使得识别加密关键字更加容易。若你使用一个字符串关键字,则 key_num 为127。结果的字符串长度为 new_len = orig_len + (8-(orig_len % 8))+1。DES关键字文件中的每一行都具有如下格式:key_num des_key_str每个key_num 必须是一个从0到0范围内的数字。文件中行的排列顺序是任意的。 des_key_str 是用来加密信息的字符串。在数字和关键字之间应该至少有一个空格。若你未指定任何到DES_ENCRYPT()的关键字参数,则第一个关键字为默认的使用关键字。使用FLUSH DES_KEY_FILE语句,你可以让 MySQL从关键字文件读取新的关键字值。这要求你享有 RELOAD特权。拥有一套默认关键字的一个好处就是它向应用程序提供了一个检验加密列值的方式,而无须向最终用户提供解密这些值的权力。mysql> SELECT customer_address FROM customer_table > WHERE crypted_credit_card = DES_ENCRYPT('credit_card_number');ENCRYPT(str[,salt])使用Unix crypt() 系统调用加密 str。 salt 参数应为一个至少包含2个字符的字符串。若没有给出 salt 参数,则使用任意值。mysql> SELECT ENCRYPT('hello'); -> 'VxuFAJXVARROc'至少在一些系统中,ENCRYPT()除了str的前八位字符之外会忽略所有内容。这个行为由下划线的crypt() 系统调用的执行所决定。假如crypt()在你的系统中不可用(正如在 Windows系统), ENCRYPT() 则会始终返回NULL。鉴于这个原因,我们向你推荐使用 MD5() 或SHA1() 来代替,因为这两个函数适合所有的平台。MD5(str)为字符串算出一个 MD5 128比特检查和。该值以32位十六进制数字的二进制字符串的形式返回, 若参数为 NULL 则会返回 NULL。例如,返回值可被用作散列关键字。mysql> SELECT MD5('testing'); -> 'ae2b1fca515949e5d54fb22b8ed95575'这是"RSA Data Security, Inc. MD5 Message-Digest Algorithm."OLD_PASSWORD(str)当PASSWORD()的执行变为改善安全性时,OLD_PASSWORD()会被添加到 MySQL。PASSWORD(str)从原文密码str 计算并返回密码字符串,当参数为 NULL 时返回 NULL。这个函数用于用户授权表的Password列中的加密MySQL密码存储mysql> SELECT PASSWORD('badpwd'); -> '7f84554057dd964b'PASSWORD() 加密是单向的 (不可逆 )。PASSWORD() 执行密码加密与Unix 密码被加密的方式不同。请参见ENCRYPT()。注释: PASSWORD()函数在MySQL服务器中的鉴定系统使用;你不应将它用在你个人的应用程序中。为达到同样目的,可使用 MD5()或SHA1() 代替。SHA1(str) SHA(str)为字符串算出一个 SHA1 160比特检查和,如RFC 3174 (安全散列算法 )中所述。该值被作为40位十六进制数字返回,而当参数为NULL 时则返回 NULL。这个函数的一个可能的用处就在于其作为散列关键字。你也可以将其作为存储密码的密码安全函数使用。mysql> SELECT SHA1('abc'); -> 'a9993e364706816aba3e25717850c26c9cd0d89d'SHA1()可以被视为一个密码更加安全的函数,相当于 MD5()。 SHA() 和SHA1()具有相同的意义。8.3 信息函数BENCHMARK(count,expr)BENCHMARK() 函数重复count 次执行表达式 expr 。 它可以被用于计算 MySQL 处理表达式的速度。结果值通常为 0。另一种用处来自 mysql客户端内部,能够报告问询执行的次数:mysql> SELECT BENCHMARK(1000000,ENCODE('hello','goodbye'));此处报告的时间是客户端上的共用时间,而不是服务器端上的CPU时间。建议执行多遍BENCHMARK(),并解释与服务器机器负荷程度有关的结果。CHARSET(str)返回字符串自变量的字符集。mysql> SELECT CHARSET('abc'); -> 'latin1' mysql> SELECT CHARSET(CONVERT('abc' USING utf8)); -> 'utf8' mysql> SELECT CHARSET(USER()); -> 'utf8'COERCIBILITY(str)返回字符串自变量的整序可压缩性值。mysql> SELECT COERCIBILITY('abc' COLLATE latin1_swedish_ci); -> 0 mysql> SELECT COERCIBILITY(USER()); -> 3 mysql> SELECT COERCIBILITY('abc'); -> 4返回值具有如下意义:下方值得优先级较高。COLLATION(str)返回惠字符串参数的排序方式。mysql> SELECT COLLATION('abc'); -> 'latin1_swedish_ci' mysql> SELECT COLLATION(_utf8'abc'); -> 'utf8_general_ci'CONNECTION_ID()返回对于连接的连接ID (线程ID)。每个连接都有各自的唯一 ID。mysql> SELECT CONNECTION_ID(); -> 23786CURRENT_USER, CURRENT_USER()返回当前话路被验证的用户名和主机名组合。这个值符合确定你的存取权限的MySQL 账户。在被指定SQL SECURITY DEFINER特征的存储程序内, CURRENT_USER() 返回程序的创建者。CURRENT_USER()的值可以和USER()的值有所不同。mysql> SELECT USER(); mysql> SELECT * FROM mysql.user; mysql> SELECT CURRENT_USER();DATABASE()返回使用 utf8 字符集的默认(当前)数据库名。在存储程序里,默认数据库是同该程序向关联的数据库,但并不一定与调用语境的默认数据库相同。mysql> SELECT DATABASE(); -> 'test'若没有默认数据库, DATABASE()返回 NULL。FOUND_ROWS()A SELECT语句可能包括一个 LIMIT 子句,用来限制服务器返回客户端的行数。在有些情况下,需要不用再次运行该语句而得知在没有LIMIT 时到底该语句返回了多少行。为了知道这个行数, 包括在SELECT 语句中选择 SQL_CALC_FOUND_ROWS ,随后调用 FOUND_ROWS() :mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name -> WHERE id > 100 LIMIT 10; mysql> SELECT FOUND_ROWS();第二个 SELECT返回一个数字,指示了在没有LIMIT子句的情况下,第一个SELECT返回了多少行 (若上述的 SELECT语句不包括 SQL_CALC_FOUND_ROWS 选项,则使用LIMIT 和不使用时,FOUND_ROWS() 可能会返回不同的结果)。通过 FOUND_ROWS()的有效行数是瞬时的,并且不用于越过SELECT SQL_CALC_FOUND_ROWS语句后面的语句。若你需要稍候参阅这个值,那么将其保存:mysql> SELECT SQL_CALC_FOUND_ROWS * FROM ... ; mysql> SET @rows = FOUND_ROWS();假如你正在使用 SELECT SQL_CALC_FOUND_ROWS, MySQL 必须计算出在全部结果集合中有所少行。然而, 这比不用LIMIT而再次运行问询要快,原因是结果集合不需要被送至客户端。SQL_CALC_FOUND_ROWS 和 FOUND_ROWS() 在当你希望限制一个问询返回的行数时很有用,同时还能不需要再次运行问询而确定全部结果集合中的行数。一个例子就是提供页式显示的Web脚本,该显示包含显示搜索结果其它部分的页的连接。使用FOUND_ROWS() 使你确定剩下的结果需要多少其它的页。SQL_CALC_FOUND_ROWS 和 FOUND_ROWS() 的应用对于UNION 问询比对于简单SELECT 语句更为复杂,原因是在UNION 中,LIMIT 可能会出现在多个位置。它可能适用于UNION中的个人 SELECT语句,或是总体上 到UNION 结果的全程。SQL_CALC_FOUND_ROWS对于 UNION的意向是它应该不需要全程LIMIT而返回应返回的行数。SQL_CALC_FOUND_ROWS 和UNION 一同使用的条件是:SQL_CALC_FOUND_ROWS 关键词必须出现在UNION的第一个 SELECT中。 FOUND_ROWS()的值只有在使用 UNION ALL时才是精确的。若使用不带ALL的UNION,则会发生两次删除, 而 FOUND_ROWS() 的指只需近似的。假若UNION 中没有出现 LIMIT ,则SQL_CALC_FOUND_ROWS 被忽略,返回临时表中的创建的用来处理UNION的行数。LAST_INSERT_ID() LAST_INSERT_ID(expr)自动返回最后一个INSERT或 UPDATE 问询为 AUTO_INCREMENT列设置的第一个发生的值。mysql> SELECT LAST_INSERT_ID(); -> 195产生的ID每次连接后保存在服务器中。这意味着函数向一个给定客户端返回的值是该客户端产生对影响AUTO_INCREMENT列的最新语句第一个 AUTO_INCREMENT值的。这个值不能被其它客户端影响,即使它们产生它们自己的 AUTO_INCREMENT值。这个行为保证了你能够找回自己的 ID 而不用担心其它客户端的活动,而且不需要加锁或处理。ROW_COUNT()ROW_COUNT()返回被前面语句升级的、插入的或删除的行数。 这个行数和 mysql 客户端显示的行数及 mysql_affected_rows() C API 函数返回的值相同。mysql> SELECT ROW_COUNT();SCHEMA()这个函数和 DATABASE()具有相同的意义。SESSION_USER()SESSION_USER()和 USER()具有相同的意义。SYSTEM_USER()SYSTEM_USER()合 USER()具有相同的意义。USER()返回当前 MySQL用户名和机主名VERSION()返回指示 MySQL 服务器版本的字符串。这个字符串使用 utf8 字符集。mysql> SELECT VERSION();注意,假如你的版本字符串以-log结尾,这说明登录已被激活。8.4 其他函数DEFAULT(col_name)返回一个表列的默认值。若该列没有默认值则会产生错误。FORMAT(X,D)将数字X 的格式写为'#,###,###.##',以四舍五入的方式保留小数点后 D 位, 并将结果以字符串的形式返回。若 D 为 0, 则返回结果不带有小数点,或不含小数部分。mysql> SELECT FORMAT(12332.123456, 4); -> '12,332.1235' mysql> SELECT FORMAT(12332.1,4); -> '12,332.1000' mysql> SELECT FORMAT(12332.2,0); -> '12,332'GET_LOCK(str,timeout)设法使用字符串str 给定的名字得到一个锁, 超时为timeout 秒。若成功得到锁,则返回 1,若操作超时则返回0 (例如,由于另一个客户端已提前封锁了这个名字 ),若发生错误则返回NULL (诸如缺乏记忆或线程mysqladmin kill 被断开 )。假如你有一个用GET_LOCK()得到的锁,当你执行RELEASE_LOCK()或你的连接断开(正常或非正常)时,这个锁就会解除。这个函数可用于执行应用程序锁或模拟记录锁定。名称被锁定在服务器范围内。假如一个名字已经被一个客户端封锁, GET_LOCK() 会封锁来自另一个客户端申请封锁同一个名字的任何请求。这使对一个封锁名达成协议的客户端使用这个名字合作执行建议锁。然而要知道它也允许不在一组合作客户端中的一个客户端封锁名字,不论是服役的还是非故意的,这样阻止任何合作中的客户端封锁这个名字。一个减少这种情况发生的办法就是使用数据库特定的或应用程序特定的封锁名。例如, 使用db_name.str或 app_name.str 形式的封锁名。mysql> SELECT GET_LOCK('lock1',10); -> 1 mysql> SELECT IS_FREE_LOCK('lock2'); -> 1 mysql> SELECT GET_LOCK('lock2',10); -> 1 mysql> SELECT RELEASE_LOCK('lock2'); -> 1 mysql> SELECT RELEASE_LOCK('lock1'); -> NULL注意,第二个 RELEASE_LOCK()调用返回 NULL ,原因是锁'lock1' 杯第二个GET_LOCK()调用解开。INET_ATON(expr)给出一个作为字符串的网络地址的点地址表示,返回一个代表该地址数值的整数。地址可以是4或8比特地址。mysql> SELECT INET_ATON('209.207.224.40'); -> 3520061480产生的数字总是按照网络字节顺序。如上面的例子,数字按照 209×2563 + 207×2562 + 224×256 + 40 进行计算。INET_ATON() 也能理解短格式 IP 地址:mysql> SELECT INET_ATON('127.0.0.1'), INET_ATON('127.1'); -> 2130706433, 2130706433注释: 在存储由INET_ATON() 产生的值时,推荐你使用 INT UNSIGNED 列。假如你使用 (带符号) INT列, 则相应的第一个八位组大于127的IP 地址值会被截至 2147483647 (即, INET_ATON('127.255.255.255') 所返回的值)。INET_NTOA(expr)给定一个数字网络地址 (4 或 8 比特),返回作为字符串的该地址的电地址表示。mysql> SELECT INET_NTOA(3520061480); -> '209.207.224.40'IS_FREE_LOCK(str)检查名为str的锁是否可以使用 (换言之,没有被封锁)。若锁可以使用,则返回 1 (没有人在用这个锁), 若这个锁正在被使用,则返回0 ,出现错误则返回 NULL (诸如不正确的参数 )。IS_USED_LOCK(str)检查名为str的锁是否正在被使用(换言之,被封锁)。若被封锁,则返回使用该锁的客户端的连接标识符。否则返回 NULL。MASTER_POS_WAIT(log_name,log_pos[,timeout])该函数对于控制主从同步很有用处。它会持续封锁,直到从设备阅读和应用主机记录中所有补充资料到指定的位置。返回值是其为到达指定位置而必须等待的记录事件的数目。若从设备SQL线程没有被启动、从设备主机信息尚未初始化、参数不正确或出现任何错误,则该函数返回 NULL。若超时时间被超过,则返回-1。若在MASTER_POS_WAIT() 等待期间,从设备SQL线程中止,则该函数返回 NULL。若从设备由指定位置通过,则函数会立即返回结果。假如已经指定了一个超时时间值,当 超时时间 秒数经过后MASTER_POS_WAIT()会停止等待。超时时间 必须大于 0;一个为零或为负值的 超时时间 表示没有超时时间。NAME_CONST(name,value)返回给定值。 当用来产生一个结果集合列时, NAME_CONST()促使该列使用给定名称。mysql> SELECT NAME_CONST('myname', 14);这个函数被添加进 MySQL 5.0.12。它只做内部使用。RELEASE_LOCK(str)解开被GET_LOCK()获取的,用字符串str 所命名的锁。若锁被解开,则返回 1,若改线程尚未创建锁,则返回0 (此时锁没有被解开 ), 若命名的锁不存在,则返回 NULL。若该锁从未被对GET_LOCK()的调用获取,或锁已经被提前解开,则该锁不存在。SLEEP(duration)睡眠(暂停) 时间为duration 参数给定的秒数,然后返回 0。若 SLEEP() 被中断,它会返回 1。 duration 或许或包括一个给定的以微秒为单位的分数部分。UUID()返回一个通用唯一标识符(UUID) ,其产生的根据是《DCE 1.1: 远程过程调用》 (附录A) CAE (公共应用软件环境) 的说明,该作品于1997年10月由 The Open Group 出版 (文件编号 C706, http://www.opengroup.org/public/pubs/catalog/c706.htm考虑到。在其它操作系统中, MySQL使用随机产生的 48比特数字。mysql> SELECT UUID(); -> '6ccd780c-baba-1026-9564-0040f4311e29'注意, UUID() 不支持复制功能。VALUES(col_name)在一个INSERT … ON DUPLICATE KEY UPDATE …语句中,你可以在UPDATE 子句中使用 VALUES(col_name)函数,用来访问来自该语句的INSERT 部分的列值。换言之,UPDATE 子句中的 VALUES(col_name) 访问需要被插入的col_name 的值,并不会发生重复键冲突。这个函数在多行插入中特别有用。 VALUES()函数只在INSERT ... UPDATE 语句中有意义,而在其它情况下只会返回 NULL。
2017年03月20日
188 阅读
0 评论
0 点赞
2017-03-16
从原理上理解NodeJS的适用场景
NodeJS是近年来比较火的服务端JS平台,这一方面得益于其在后端处理高并发的卓越性能,另一方面在nodeJS平台上的npm、grunt、express等强大的代码与项目管理应用崛起,几乎重新定义了前端的工作方式和流程。NodeJS的成功标志着它的强大,但是不是所有情况都适合应用NodeJS作为服务器端平台呢?答案当然是否定的,而网上也是众说纷纭。那我们从原理出发了解一下NodeJS的适用情况。在讲NodeJS之前我们不仿先看一下传统(以Apache为代表)的服务器端处理平台处理并发的方式。Apache的多线程高并发模式Apache是当前世界排名第一的Web服务端软件,它由于支持多线程并发而受到广大服务器技术选型者的欢迎。但发展到后来,Apache在一些WEB的大型应用中也渐渐暴露出它的缺点:阻塞。那有的同学会奇怪,Apache不是多线程处理并发吗,为什么还会出现阻塞呢?要明白这一点我们首先需要了解线程这个概念1.1 什么是线程?我们引用官方的解释:线程可以独立运行的最小的CPU单位,可以在同一个进程里并发运行,共享该进程下的内存地址空间(注意这个特点)。我们可以看到同一个进程下的线程是会共享相同的文件和内存的(内存地址空间),所以大家可以想象,当不同的线程需要占用同一个变量时,根据先到先得的原则,先到的线程在运作时,后来的线程只能在旁边等待,也就是加入到了阻塞排队序列。所以这就是造成线程阻塞的原因。因此,虽说进程可以支持多个线程,它们看似同时执行,但互相之间并不同步。一个进程中的多个线程共享相同的内存地址空间,这就意味着它们可以访问相同的变量和对象,而且它们从同一堆中分配对象。尽管这让线程之间共享信息变得更容易,因为程序设计者必须小心,确保它们不会妨碍同一进程里的其它线程。了解了多线程并行的缺陷后,我们就可以更好地理解NodeJS的强大所在了。因为NodeJS是异步单线程的!NodeJS的异步I/O原理我们先来看一段Apache请求数据库的代码:代码执行到第一行的时候线程会阻塞,等待query返回结果,然后继续处理。由于数据库查询、磁盘读写、网络通信等原因(所谓的I/O)阻塞时间会非常大(相对于CPU始终频率)。对于高并发的访问,一方面线程长期阻塞等待,另一方面为了应付新情求而不断添加新线程,会浪费大量系统资源,同时线程的增加也会也会占用大量的CPU时间来处理内存上下文切换。看看node.js怎么处理。看到没,就四个字:异步回调。query的第二个参数是一个回调函数,进程执行到db.query的时候不会等待结果返回,而是直接继续执行下面的语句,直到进入事件循环。当数据库执行结果返回的时候会将事件发送到事件队列,等到线程进入事件循环后才会调用之前的回调函数。更专业的说法是异步I/O。只要单线程就可以。那为什么NodeJS做到单线程,却可以实现异步呢?在这里我们先上一幅图,直戳图中的Event queue看到没,NodeJS的工作原理其实就是事件循环。可以说每一条NodeJS的逻辑都是写在回调函数里面的,而回调函数都是有返回之后才异步执行的!看到这里,你不禁会惊叹,NodeJS如果所有处理都异步,岂不是晓得飞了?错错错!当然不是,不要忘记,NodeJS实现这些的基础是单线程。没错,单线程!一条线程扛起所有操作!你可以想象一下,NodeJS在寒风中面对着10万并发大军,OK,没问题,上来敌人一个扔到城里,上来一个又扔到城里。城里全民皆兵,可以很好地消化这些敌人。但如果上来一个类似于张飞赵云这样的人物,老Node心里一惨,和张飞大战300回合,把他打残了,再扔到城里。那后面的10万大军就得等这300回合。。。所以这说明什么?说明NodeJS不是没有阻塞,而是阻塞不发生在后续回调的流程,而会发生在NodeJS本身对逻辑的计算和处理。我们已经知道,NodeJS的分发能力无比强大,可以循环事件进行异步回调。但如果在循环事件时遇到复杂的逻辑运算,那么单薄的单线程怎么支撑得起上百万的逻辑+并发呢?NodeJS它的所有I/O、网络通信等比较耗时的操作,都可以交给worker threads执行再回调,所以很快。但CPU的正常操作,它就只能自己抗了。 说到这里,各位对NodeJS的特性估计也大概有个谱了。所以说适用的场景基本是呼之欲出了~!NodeJS的应用场景既然NodeJS处理并发的能力强,但处理计算和逻辑的能力反而很弱,因此,如果我们把复杂的逻辑运算都搬到前端(客户端)完成,而NodeJS只需要提供异步I/O,这样就可以实现对高并发的高性能处理。情况就很多啦,比如:RESTFUL API、实时聊天、客户端逻辑强大的单页APP,具体的例子比如说:本地化的在线音乐应用,本地化的在线搜索应用,本地化的在线APP等。顺便提一下Apache,打压了这么多,给颗甜枣。Apache由于其多线程高并发共享内存地址空间的特性,那就意味着如果服务器足够强大,处理器足够高核,Apache的运作将会非常良好,所以适用于(并发)异步处理相对较少,后台计算量大,后台业务逻辑复杂的应用程序。
2017年03月16日
182 阅读
0 评论
0 点赞
2016-11-15
JavaScript删除数组重复元素的5个高效算法-变内置方法
1.遍历数组法最简单的去重方法, 实现思路:新建一新数组,遍历传入数组,值不在新数组就加入该新数组中;注意点:判断值是否在数组的方法“indexOf”是ECMAScript5 方法,IE8以下不支持,需多写一些兼容低版本浏览器代码,源码如下:// 最简单数组去重法 function unique1(array){ var n = []; //一个新的临时数组 //遍历当前数组 for(var i = 0; i < array.length; i++){ //如果当前数组的第i已经保存进了临时数组,那么跳过, //否则把当前项push到临时数组里面 if (n.indexOf(array[i]) == -1) n.push(array[i]); } return n; }// 判断浏览器是否支持indexOf ,indexOf 为ecmaScript5新方法 IE8以下(包括IE8, IE8只支持部分ecma5)不支持 if (!Array.prototype.indexOf){ // 新增indexOf方法 Array.prototype.indexOf = function(item){ var result = -1, a_item = null; if (this.length == 0){ return result; } for(var i = 0, len = this.length; i < len; i++){ a_item = this[i]; if (a_item === item){ result = i; break; } } return result; } } 2.对象键值对法该方法执行的速度比其他任何方法都快, 就是占用的内存大一些;实现思路:新建一js对象以及新数组,遍历传入数组时,判断值是否为js对象的键,不是的话给对象新增该键并放入新数组。注意点: 判断是否为js对象键时,会自动对传入的键执行“toString()”,不同的键可能会被误认为一样;例如: a[1]、a["1"] 。解决上述问题还是得调用“indexOf”。// 速度最快, 占空间最多(空间换时间) function unique2(array){ var n = {}, r = [], len = array.length, val, type; for (var i = 0; i < array.length; i++) { val = array[i]; type = typeof val; if (!n[val]) { n[val] = [type]; r.push(val); } else if (n[val].indexOf(type) < 0) { n[val].push(type); r.push(val); } } return r; }3.数组下标判断法还是得调用“indexOf”性能跟方法1差不多,实现思路:如果当前数组的第i项在当前数组中第一次出现的位置不是i,那么表示第i项是重复的,忽略掉。否则存入结果数组。function unique3(array){ var n = [array[0]]; //结果数组 //从第二项开始遍历 for(var i = 1; i < array.length; i++) { //如果当前数组的第i项在当前数组中第一次出现的位置不是i, //那么表示第i项是重复的,忽略掉。否则存入结果数组 if (array.indexOf(array[i]) == i) n.push(array[i]); } return n; }4.排序后相邻去除法虽然原生数组的”sort”方法排序结果不怎么靠谱,但在不注重顺序的去重里该缺点毫无影响。实现思路:给传入数组排序,排序后相同值相邻,然后遍历时新数组只加入不与前一值重复的值。// 将相同的值相邻,然后遍历去除重复值 function unique4(array){ array.sort(); var re=[array[0]]; for(var i = 1; i < array.length; i++){ if( array[i] !== re[re.length-1]) { re.push(array[i]); } } return re; }5.优化遍历数组法源自外国博文,该方法的实现代码相当酷炫;实现思路:获取没重复的最右一值放入新数组。(检测到有重复值时终止当前循环同时进入顶层循环的下一轮判断)// 思路:获取没重复的最右一值放入新数组 function unique5(array){ var r = []; for(var i = 0, l = array.length; i < l; i++) { for(var j = i + 1; j < l; j++) if (array[i] === array[j]) j = ++i; r.push(array[i]); } return r; }综上所述,那么我们为了节约命名空间就干脆做一个Array的内置方法嵌入进去好了,我这么写:/** * //--数组去除重复元素------ * @param array * @returns {Array} */ window.Array.prototype.unique = function (){ var r = []; for(var i = 0, l = this.length; i < l; i++) { for(var j = i + 1; j < l; j++) if (this[i] === this[j]) j = ++i; r.push(this[i]);} return r; }; //---使用 var arr=[1,2,2,1,3,4].unique(); alert(arr); //结果 2,1,3,4 如果想要更高效的方法,那么您关注这里的持续更新吧
2016年11月15日
123 阅读
0 评论
0 点赞
2016-02-03
Animate.css CSS3动画库,使用优化版
Animate.css是一个来自国外的 CSS3 动画库,它预设了抖动(shake)、闪烁(flash)、弹跳(bounce)、翻转(flip)、旋转(rotateIn/rotateOut)、淡入淡出(fadeIn/fadeOut)等多达 60 多种动画效果,几乎包含了所有常见的动画效果。开发者封装了一些常用的特效效果作为className方便码农使用,以下我简单描述下它怎么玩及分享一个js动态加载的一个优化方法。
2016年02月03日
190 阅读
0 评论
0 点赞
2015-11-09
ecshop订单表结构ecs_order_info说明
-- 表的结构 ecs_order_info CREATE TABLE IF NOT EXISTS `ecs_order_info` ( `order_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT COMMENT '订单详细信息自增id', `order_sn` varchar(20) NOT NULL COMMENT '订单号,唯一', `user_id` mediumint(8) unsigned NOT NULL DEFAULT '0' COMMENT '用户id,同ecs_users的user_id', `order_status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '订单状态。0,未确认;1,已确认;2,已取消;3,无效;4,退货;', `shipping_status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '商品配送情况,0,未发货;1,已发货;2,已收货;3,备货中', `pay_status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '支付状态;0,未付款;1,付款中;2,已付款', `consignee` varchar(60) NOT NULL COMMENT '收货人的姓名,用户页面填写,默认取值于表user_address', `country` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT '收货人的国家,用户页面填写,默认取值于表user_address,其id对应的值在ecs_region', `province` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT '收货人的省份,用户页面填写,默认取值于表user_address,其id对应的值在ecs_region', `city` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT '收货人的城市,用户页面填写,默认取值于表user_address,其id对应的值在ecs_region', `district` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT '收货人的地区,用户页面填写,默认取值于表user_address,其id对应的值在ecs_region', `address` varchar(255) NOT NULL COMMENT '收货人的详细地址,用户页面填写,默认取值于表user_address', `zipcode` varchar(60) NOT NULL COMMENT '收货人的邮编,用户页面填写,默认取值于表user_address', `tel` varchar(60) NOT NULL COMMENT '收货人的电话,用户页面填写,默认取值于表user_address', `mobile` varchar(60) NOT NULL COMMENT '收货人的手机,用户页面填写,默认取值于表user_address', `email` varchar(60) NOT NULL COMMENT '收货人的手机,用户页面填写,默认取值于表user_address', `best_time` varchar(120) NOT NULL COMMENT '收货人的最佳送货时间,用户页面填写,默认取值于表user_address', `sign_building` varchar(120) NOT NULL COMMENT '收货人的地址的标志性建筑,用户页面填写,默认取值于表user_address', `postscript` varchar(255) NOT NULL COMMENT '订单附言,由用户提交订单前填写', `shipping_id` tinyint(3) NOT NULL DEFAULT '0' COMMENT '用户选择的配送方式id,取值表ecs_shipping', `shipping_name` varchar(120) NOT NULL COMMENT '用户选择的配送方式的名称,取值表ecs_shipping', `pay_id` tinyint(3) NOT NULL DEFAULT '0' COMMENT '用户选择的支付方式的id,取值表ecs_payment', `pay_name` varchar(120) NOT NULL COMMENT '用户选择的支付方式的名称,取值表ecs_payment', `how_oos` varchar(120) NOT NULL COMMENT '缺货处理方式,等待所有商品备齐后再发; 取消订单;与店主协商', `how_surplus` varchar(120) NOT NULL COMMENT '根据字段猜测应该是余额处理方式,程序未作这部分实现', `pack_name` varchar(120) NOT NULL COMMENT '包装名称,取值表ecs_pack', `card_name` varchar(120) NOT NULL COMMENT '贺卡的名称,取值ecs_card ', `card_message` varchar(255) NOT NULL COMMENT '贺卡内容,由用户提交', `inv_payee` varchar(120) NOT NULL COMMENT '发票抬头,用户页面填写', `inv_content` varchar(120) NOT NULL COMMENT '发票内容,用户页面选择,取值ecs_shop_config的code字段的值为invoice_content的value', `goods_amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '商品总金额', `shipping_fee` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '配送费用', `insure_fee` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '保价费用', `pay_fee` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '支付费用,跟支付方式的配置相关,取值表ecs_payment', `pack_fee` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '包装费用,取值表取值表ecs_pack', `card_fee` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '贺卡费用,取值ecs_card ', `money_paid` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '已付款金额', `surplus` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '该订单使用余额的数量,取用户设定余额,用户可用余额,订单金额中最小者', `integral` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用的积分的数量,取用户使用积分,商品可用积分,用户拥有积分中最小者', `integral_money` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '使用积分金额', `bonus` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '使用红包金额', `order_amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '应付款金额', `from_ad` smallint(5) NOT NULL DEFAULT '0' COMMENT '订单由某广告带来的广告id,应该取值于ecs_ad', `referer` varchar(255) NOT NULL COMMENT '订单的来源页面', `add_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '订单生成时间', `confirm_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '订单确认时间', `pay_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '订单支付时间', `shipping_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '订单配送时间', `pack_id` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '包装id,取值取值表ecs_pack', `card_id` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '贺卡id,用户在页面选择,取值取值ecs_card ', `bonus_id` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT '红包的id,ecs_user_bonus的bonus_id', `invoice_no` varchar(50) NOT NULL COMMENT '发货单号,发货时填写,可在订单查询查看', `extension_code` varchar(30) NOT NULL COMMENT '通过活动购买的商品的代号;GROUP_BUY是团购;AUCTION,是拍卖;SNATCH,夺宝奇兵;正常普通产品该处为空', `extension_id` mediumint(8) unsigned NOT NULL DEFAULT '0' COMMENT '通过活动购买的物品的id,取值ecs_goods_activity;如果是正常普通商品,该处为0', `to_buyer` varchar(255) NOT NULL COMMENT '商家给客户的留言,当该字段有值时可以在订单查询看到', `pay_note` varchar(255) NOT NULL COMMENT '付款备注,在订单管理里编辑修改', `agency_id` smallint(5) unsigned NOT NULL COMMENT '该笔订单被指派给的办事处的id,根据订单内容和办事处负责范围自动决定,也可以有管理员修改,取值于表ecs_agency', `inv_type` varchar(60) NOT NULL COMMENT '发票类型,用户页面选择,取值ecs_shop_config的code字段的值为invoice_type的value', `tax` decimal(10,2) NOT NULL COMMENT '发票税额', `is_separate` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0,未分成或等待分成;1,已分成;2,取消分成;', `parent_id` mediumint(8) unsigned NOT NULL DEFAULT '0' COMMENT '能获得推荐分成的用户id,id取值于表ecs_users', `discount` decimal(10,2) NOT NULL COMMENT '折扣金额', PRIMARY KEY (`order_id`), UNIQUE KEY `order_sn` (`order_sn`), KEY `user_id` (`user_id`), KEY `order_status` (`order_status`), KEY `shipping_status` (`shipping_status`), KEY `pay_status` (`pay_status`), KEY `shipping_id` (`shipping_id`), KEY `pay_id` (`pay_id`), KEY `extension_code` (`extension_code`,`extension_id`), KEY `agency_id` (`agency_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='订单的配送,贺卡等详细信息' AUTO_INCREMENT=24 ;
2015年11月09日
358 阅读
0 评论
0 点赞
2015-09-15
webapp上下左右拖动,回调函数 jQuery插件,改造版本
本jQuery插件方法用于感应上下左右的滑动动作并执行对应的回掉函数,您可以自行建立一个js文件供加载使用/* 用于获取上下左右的拖动事件 $('#box').swipeleft( //--回调函数1 - 滑动开始时 function(n,s){ n=速度 越小标识越快 s=步长 滑动的距离 }, //--回调函数2 - 滑动结束后 function(xy){ xy=x或y的点阵位置 swipeleft swiperight = x swipetop swipedown = y }, v //--滑动在多少毫秒内才感应 默认300 ); */ (function($){ var v=300;//--300以内执行传递参数 var t=[0,0]; $.fn.extend({//局部插件,去掉.fn是全局插件 'swipeleft':function(fn,fn2,_v){//手指左滑动,fn是回调函数 v=_v?_v:v; $(this).on('touchstart',function(e){ e=e.originalEvent.touches[0];//获取对应触摸对象 var sx=0; sx=e.pageX; if(fn2) fn2(sx); t[0]=$(this).transdate(); $(this).on('touchend',function(e){ t[1]=$(this).transdate(); var n=t[1]-t[0]; e=e.originalEvent.changedTouches[0];//获取对应触摸对象 var s=sx-e.pageX; if((v>=n) && s>50){//如果滑动距离大于50px就认为是要触发左滑动事件了 fn(n,s);//调用回调函数 } $(this).unbind('touchend'); }); }); return this; }, 'swiperight':function(fn,fn2,_v){//手指右滑动,fn是回调函数 v=_v?_v:v; $(this).on('touchstart',function(e){ e=e.originalEvent.touches[0];//获取对应触摸对象 var sx=0; sx=e.pageX; if(fn2) fn2(sx); t[0]=$(this).transdate(); $(this).on('touchend',function(e){ t[1]=$(this).transdate(); var n=t[1]-t[0]; e=e.originalEvent.changedTouches[0];//获取对应触摸对象 var s=e.pageX-sx; if((v>=n) && s>50){//如果滑动距离大于50px就认为是要触发右滑动事件了 fn(n,s);//调用回调函数 } $(this).unbind('touchend'); }); }); }, 'swipetop':function(fn,fn2,_v){//手指上滑动,fn是回调函数 v=_v?_v:v; $(this).on('touchstart',function(e){ e=e.originalEvent.touches[0];//获取对应触摸对象 var sy=0; sy=e.pageY; if(fn2) fn2(sy); t[0]=$(this).transdate(); $(this).on('touchend',function(e){ t[1]=$(this).transdate(); var n=t[1]-t[0]; e=e.originalEvent.changedTouches[0];//获取对应触摸对象 var s=sy-e.pageY; if((v>=n) && s>50){//如果滑动距离大于50px就认为是要触发上滑动事件了 fn(n,s);//调用回调函数 } $(this).unbind('touchend'); }); }); }, 'swipedown':function(fn,fn2,_v){//手指下滑动,fn是回调函数 v=_v?_v:v; $(this).on('touchstart',function(e){ e=e.originalEvent.touches[0];//获取对应触摸对象 var sy=0; sy=e.pageY; if(fn2) fn2(sy); t[0]=$(this).transdate(); $(this).on('touchend',function(e){ t[1]=$(this).transdate(); var n=t[1]-t[0]; e=e.originalEvent.changedTouches[0];//获取对应触摸对象 var s=e.pageY-sy; if((v>=n) && s>50){//如果滑动距离大于50px就认为是要触发下滑动事件了 fn(n,s);//调用回调函数 } $(this).unbind('touchend'); }); }); }, 'transdate': function (){return Number(new Date().getTime());} }); })(jQuery);
2015年09月15日
209 阅读
0 评论
0 点赞
1
2