diff --git a/404.html b/404.html
new file mode 100644
index 00000000..b062c6e3
--- /dev/null
+++ b/404.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+ DB-TUTORIAL
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/archives/index.html b/archives/index.html
new file mode 100644
index 00000000..0b79a5e7
--- /dev/null
+++ b/archives/index.html
@@ -0,0 +1,223 @@
+
+
+
+
+
+ 归档 | DB-TUTORIAL
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/css/0.styles.77b73934.css b/assets/css/0.styles.77b73934.css
new file mode 100644
index 00000000..1dfbe2e4
--- /dev/null
+++ b/assets/css/0.styles.77b73934.css
@@ -0,0 +1 @@
+@import url(//at.alicdn.com/t/font_1678482_4tbhmh589x.css);.code-copy{color:#aaa;fill:#aaa;font-size:14px;display:inline-block;cursor:pointer}div[class*=aside-code] aside .code-copy,div[class*=language-] pre .code-copy{position:absolute;z-index:1000;top:7px;right:35px;opacity:0;font-size:16px}div[class*=aside-code] aside:hover .code-copy,div[class*=language-] pre:hover .code-copy{opacity:1}.content pre,.content pre[class*=language-]{overflow-y:hidden}div[class*=language-] pre,div[class*=language-] pre[class*=language-]{position:static!important}div[class~=language-text]:before{content:"text"}div[class~=language-yml]:before{content:"yml"}div[class*=language-] pre{-webkit-user-select:text;-moz-user-select:text;user-select:text}p code{-webkit-user-select:all;-moz-user-select:all;user-select:all}@keyframes message-move-in{0%{opacity:0;transform:translateY(-100%)}to{opacity:1;transform:translateY(0)}}#message-container .message.move-in{animation:message-move-in .3s ease-in-out}@keyframes message-move-out{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-100%)}}#message-container .message.move-out{animation:message-move-out .3s ease-in-out;animation-fill-mode:forwards}#message-container .message{background:#fff;margin:10px 0;padding:0 10px;height:40px;box-shadow:0 0 10px 0 #ccc;font-size:14px;border-radius:3px;display:flex;align-items:center;transition:height .2s ease-in-out,margin .2s ease-in-out}#message-container{position:fixed;left:0;top:100px;right:0;display:flex;flex-direction:column;align-items:center}#message-container .message .text{color:#333;padding:0 20px 0 5px}.theme-code-block[data-v-4f1e9d0c]{display:none}.theme-code-block__active[data-v-4f1e9d0c]{display:block}.theme-code-block>pre[data-v-4f1e9d0c]{background-color:orange}@media (max-width:419px){.theme-code-group div[class*=language-][data-v-4f1e9d0c]{margin:0}}.theme-mode-light[data-v-2f5f1757]{--bodyBg:#f4f4f4;--customBlockBg:#f1f1f1;--textColor:#00323c;--borderColor:rgba(0,0,0,0.12)}.theme-mode-dark[data-v-2f5f1757]{--bodyBg:#27272b;--customBlockBg:#27272b;--textColor:#9b9baa;--borderColor:#30363d}.theme-mode-read[data-v-2f5f1757]{--bodyBg:#ececcc;--customBlockBg:#ececcc;--textColor:#704214;--textLightenColor:#963}.theme-style-line.theme-mode-light[data-v-2f5f1757]{--bodyBg:#fff}.theme-style-line.theme-mode-dark[data-v-2f5f1757]{--bodyBg:#1e1e22}.theme-style-line.theme-mode-read[data-v-2f5f1757]{--bodyBg:#f5f5d5}.theme-mode-light[data-v-2f5f1757]{--bodyBg:#fff;--mainBg:#fff;--sidebarBg:hsla(0,0%,100%,0.8);--blurBg:hsla(0,0%,100%,0.9);--textColor:#004050;--textLightenColor:#0085ad;--borderColor:rgba(0,0,0,0.15);--codeBg:#f6f6f6;--codeColor:#525252}.theme-mode-light code[class*=language-][data-v-2f5f1757],.theme-mode-light pre[class*=language-][data-v-2f5f1757]{color:#000;background:none;text-shadow:0 1px #fff;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-light code[class*=language-][data-v-2f5f1757]::-moz-selection,.theme-mode-light code[class*=language-][data-v-2f5f1757] ::-moz-selection,.theme-mode-light pre[class*=language-][data-v-2f5f1757]::-moz-selection,.theme-mode-light pre[class*=language-][data-v-2f5f1757] ::-moz-selection{text-shadow:none;background:#b3d4fc}.theme-mode-light code[class*=language-][data-v-2f5f1757]::selection,.theme-mode-light code[class*=language-][data-v-2f5f1757] ::selection,.theme-mode-light pre[class*=language-][data-v-2f5f1757]::selection,.theme-mode-light pre[class*=language-][data-v-2f5f1757] ::selection{text-shadow:none;background:#b3d4fc}@media print{.theme-mode-light code[class*=language-][data-v-2f5f1757],.theme-mode-light pre[class*=language-][data-v-2f5f1757]{text-shadow:none}}.theme-mode-light pre[class*=language-][data-v-2f5f1757]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-light :not(pre)>code[class*=language-][data-v-2f5f1757],.theme-mode-light pre[class*=language-][data-v-2f5f1757]{background:#f5f2f0}.theme-mode-light :not(pre)>code[class*=language-][data-v-2f5f1757]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-light .token.cdata[data-v-2f5f1757],.theme-mode-light .token.comment[data-v-2f5f1757],.theme-mode-light .token.doctype[data-v-2f5f1757],.theme-mode-light .token.prolog[data-v-2f5f1757]{color:#708090}.theme-mode-light .token.punctuation[data-v-2f5f1757]{color:#999}.theme-mode-light .namespace[data-v-2f5f1757]{opacity:.7}.theme-mode-light .token.boolean[data-v-2f5f1757],.theme-mode-light .token.constant[data-v-2f5f1757],.theme-mode-light .token.deleted[data-v-2f5f1757],.theme-mode-light .token.number[data-v-2f5f1757],.theme-mode-light .token.property[data-v-2f5f1757],.theme-mode-light .token.symbol[data-v-2f5f1757],.theme-mode-light .token.tag[data-v-2f5f1757]{color:#905}.theme-mode-light .token.attr-name[data-v-2f5f1757],.theme-mode-light .token.builtin[data-v-2f5f1757],.theme-mode-light .token.char[data-v-2f5f1757],.theme-mode-light .token.inserted[data-v-2f5f1757],.theme-mode-light .token.selector[data-v-2f5f1757],.theme-mode-light .token.string[data-v-2f5f1757]{color:#690}.theme-mode-light .language-css .token.string[data-v-2f5f1757],.theme-mode-light .style .token.string[data-v-2f5f1757],.theme-mode-light .token.entity[data-v-2f5f1757],.theme-mode-light .token.operator[data-v-2f5f1757],.theme-mode-light .token.url[data-v-2f5f1757]{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.theme-mode-light .token.atrule[data-v-2f5f1757],.theme-mode-light .token.attr-value[data-v-2f5f1757],.theme-mode-light .token.keyword[data-v-2f5f1757]{color:#07a}.theme-mode-light .token.class-name[data-v-2f5f1757],.theme-mode-light .token.function[data-v-2f5f1757]{color:#dd4a68}.theme-mode-light .token.important[data-v-2f5f1757],.theme-mode-light .token.regex[data-v-2f5f1757],.theme-mode-light .token.variable[data-v-2f5f1757]{color:#e90}.theme-mode-light .token.bold[data-v-2f5f1757],.theme-mode-light .token.important[data-v-2f5f1757]{font-weight:700}.theme-mode-light .token.italic[data-v-2f5f1757]{font-style:italic}.theme-mode-light .token.entity[data-v-2f5f1757]{cursor:help}.theme-mode-light div[class*=language-] .highlight-lines .highlighted[data-v-2f5f1757],.theme-mode-light div[class*=language-].line-numbers-mode .highlight-lines .highlighted[data-v-2f5f1757]:before{background-color:hsla(0,0%,78.4%,.4)}.theme-mode-dark[data-v-2f5f1757]{--bodyBg:#1e1e22;--mainBg:#1e1e22;--sidebarBg:rgba(30,30,34,0.8);--blurBg:rgba(30,30,34,0.8);--textColor:#8c8c96;--textLightenColor:#0085ad;--borderColor:#2c2c3a;--codeBg:#252526;--codeColor:#fff}.theme-mode-dark code[class*=language-][data-v-2f5f1757],.theme-mode-dark pre[class*=language-][data-v-2f5f1757]{color:#ccc;background:none;text-shadow:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-dark pre[class*=language-][data-v-2f5f1757]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-dark :not(pre)>code[class*=language-][data-v-2f5f1757],.theme-mode-dark pre[class*=language-][data-v-2f5f1757]{background:#2d2d2d}.theme-mode-dark :not(pre)>code[class*=language-][data-v-2f5f1757]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-dark .token.block-comment[data-v-2f5f1757],.theme-mode-dark .token.cdata[data-v-2f5f1757],.theme-mode-dark .token.comment[data-v-2f5f1757],.theme-mode-dark .token.doctype[data-v-2f5f1757],.theme-mode-dark .token.prolog[data-v-2f5f1757]{color:#999}.theme-mode-dark .token.punctuation[data-v-2f5f1757]{color:#ccc}.theme-mode-dark .token.attr-name[data-v-2f5f1757],.theme-mode-dark .token.deleted[data-v-2f5f1757],.theme-mode-dark .token.namespace[data-v-2f5f1757],.theme-mode-dark .token.tag[data-v-2f5f1757]{color:#e2777a}.theme-mode-dark .token.function-name[data-v-2f5f1757]{color:#6196cc}.theme-mode-dark .token.boolean[data-v-2f5f1757],.theme-mode-dark .token.function[data-v-2f5f1757],.theme-mode-dark .token.number[data-v-2f5f1757]{color:#f08d49}.theme-mode-dark .token.class-name[data-v-2f5f1757],.theme-mode-dark .token.constant[data-v-2f5f1757],.theme-mode-dark .token.property[data-v-2f5f1757],.theme-mode-dark .token.symbol[data-v-2f5f1757]{color:#f8c555}.theme-mode-dark .token.atrule[data-v-2f5f1757],.theme-mode-dark .token.builtin[data-v-2f5f1757],.theme-mode-dark .token.important[data-v-2f5f1757],.theme-mode-dark .token.keyword[data-v-2f5f1757],.theme-mode-dark .token.selector[data-v-2f5f1757]{color:#cc99cd}.theme-mode-dark .token.attr-value[data-v-2f5f1757],.theme-mode-dark .token.char[data-v-2f5f1757],.theme-mode-dark .token.regex[data-v-2f5f1757],.theme-mode-dark .token.string[data-v-2f5f1757],.theme-mode-dark .token.variable[data-v-2f5f1757]{color:#7ec699}.theme-mode-dark .token.entity[data-v-2f5f1757],.theme-mode-dark .token.operator[data-v-2f5f1757],.theme-mode-dark .token.url[data-v-2f5f1757]{color:#67cdcc}.theme-mode-dark .language-css .token.string[data-v-2f5f1757],.theme-mode-dark .style .token.string[data-v-2f5f1757],.theme-mode-dark .token.entity[data-v-2f5f1757],.theme-mode-dark .token.operator[data-v-2f5f1757],.theme-mode-dark .token.url[data-v-2f5f1757]{background:none}.theme-mode-dark .token.bold[data-v-2f5f1757],.theme-mode-dark .token.important[data-v-2f5f1757]{font-weight:700}.theme-mode-dark .token.italic[data-v-2f5f1757]{font-style:italic}.theme-mode-dark .token.entity[data-v-2f5f1757]{cursor:help}.theme-mode-dark .token.inserted[data-v-2f5f1757]{color:green}.theme-mode-read[data-v-2f5f1757]{--bodyBg:#f5f5d5;--mainBg:#f5f5d5;--sidebarBg:rgba(245,245,213,0.8);--blurBg:rgba(245,245,213,0.9);--textColor:#004050;--textLightenColor:#0085ad;--borderColor:rgba(0,0,0,0.15);--codeBg:#282c34;--codeColor:#fff}.theme-mode-read code[class*=language-][data-v-2f5f1757],.theme-mode-read pre[class*=language-][data-v-2f5f1757]{color:#ccc;background:none;text-shadow:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-read pre[class*=language-][data-v-2f5f1757]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-read :not(pre)>code[class*=language-][data-v-2f5f1757],.theme-mode-read pre[class*=language-][data-v-2f5f1757]{background:#2d2d2d}.theme-mode-read :not(pre)>code[class*=language-][data-v-2f5f1757]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-read .token.block-comment[data-v-2f5f1757],.theme-mode-read .token.cdata[data-v-2f5f1757],.theme-mode-read .token.comment[data-v-2f5f1757],.theme-mode-read .token.doctype[data-v-2f5f1757],.theme-mode-read .token.prolog[data-v-2f5f1757]{color:#999}.theme-mode-read .token.punctuation[data-v-2f5f1757]{color:#ccc}.theme-mode-read .token.attr-name[data-v-2f5f1757],.theme-mode-read .token.deleted[data-v-2f5f1757],.theme-mode-read .token.namespace[data-v-2f5f1757],.theme-mode-read .token.tag[data-v-2f5f1757]{color:#e2777a}.theme-mode-read .token.function-name[data-v-2f5f1757]{color:#6196cc}.theme-mode-read .token.boolean[data-v-2f5f1757],.theme-mode-read .token.function[data-v-2f5f1757],.theme-mode-read .token.number[data-v-2f5f1757]{color:#f08d49}.theme-mode-read .token.class-name[data-v-2f5f1757],.theme-mode-read .token.constant[data-v-2f5f1757],.theme-mode-read .token.property[data-v-2f5f1757],.theme-mode-read .token.symbol[data-v-2f5f1757]{color:#f8c555}.theme-mode-read .token.atrule[data-v-2f5f1757],.theme-mode-read .token.builtin[data-v-2f5f1757],.theme-mode-read .token.important[data-v-2f5f1757],.theme-mode-read .token.keyword[data-v-2f5f1757],.theme-mode-read .token.selector[data-v-2f5f1757]{color:#cc99cd}.theme-mode-read .token.attr-value[data-v-2f5f1757],.theme-mode-read .token.char[data-v-2f5f1757],.theme-mode-read .token.regex[data-v-2f5f1757],.theme-mode-read .token.string[data-v-2f5f1757],.theme-mode-read .token.variable[data-v-2f5f1757]{color:#7ec699}.theme-mode-read .token.entity[data-v-2f5f1757],.theme-mode-read .token.operator[data-v-2f5f1757],.theme-mode-read .token.url[data-v-2f5f1757]{color:#67cdcc}.theme-mode-read .language-css .token.string[data-v-2f5f1757],.theme-mode-read .style .token.string[data-v-2f5f1757],.theme-mode-read .token.entity[data-v-2f5f1757],.theme-mode-read .token.operator[data-v-2f5f1757],.theme-mode-read .token.url[data-v-2f5f1757]{background:none}.theme-mode-read .token.bold[data-v-2f5f1757],.theme-mode-read .token.important[data-v-2f5f1757]{font-weight:700}.theme-mode-read .token.italic[data-v-2f5f1757]{font-style:italic}.theme-mode-read .token.entity[data-v-2f5f1757]{cursor:help}.theme-mode-read .token.inserted[data-v-2f5f1757]{color:green}.theme-code-group[data-v-2f5f1757],.theme-code-group__nav[data-v-2f5f1757]{background-color:var(--codeBg);padding-bottom:22px;border-radius:6px;padding-left:10px;padding-top:10px}.theme-code-group__nav[data-v-2f5f1757]{margin-bottom:-35px}.theme-code-group__ul[data-v-2f5f1757]{margin:auto 0;padding-left:0;display:inline-flex;list-style:none}.theme-code-group__li[data-v-2f5f1757],.theme-code-group__nav-tab[data-v-2f5f1757]{border:0;padding:5px;cursor:pointer;background-color:transparent;font-size:.85em;line-height:1.4;color:var(--codeColor);font-weight:600;opacity:.85}.theme-code-group__nav-tab-active[data-v-2f5f1757]{border-bottom:1px solid #11a8cd;opacity:1}.pre-blank[data-v-2f5f1757]{color:#11a8cd}body .theme-vdoing-content code{color:var(--textLightenColor);padding:.25rem .5rem;margin:0;font-size:.9em;background-color:hsla(0,0%,39.2%,.08);border-radius:3px}body .theme-vdoing-content code .token.deleted{color:#ec5975}body .theme-vdoing-content code .token.inserted{color:#11a8cd}body .theme-vdoing-content pre,body .theme-vdoing-content pre[class*=language-]{line-height:1.4;padding:1.25rem 1.5rem;margin:.85rem 0;background-color:#282c34;border-radius:6px;overflow:auto}body .theme-vdoing-content pre[class*=language-] code,body .theme-vdoing-content pre code{color:var(--codeColor);padding:0;background-color:transparent;border-radius:0}div[class*=language-]{position:relative;background-color:var(--codeBg);border-radius:6px}div[class*=language-] .highlight-lines{-webkit-user-select:none;user-select:none;padding-top:1.3rem;position:absolute;top:0;left:0;width:100%;line-height:1.4}div[class*=language-] .highlight-lines .highlighted{background-color:rgba(0,0,0,.3)}div[class*=language-] pre,div[class*=language-] pre[class*=language-]{background:transparent;position:relative!important;z-index:1}div[class*=language-]:before{position:absolute;z-index:3;top:.8em;right:1em;font-size:.8rem;color:hsla(0,0%,58.8%,.7)}div[class*=language-]:not(.line-numbers-mode) .line-numbers-wrapper{display:none}div[class*=language-].line-numbers-mode .highlight-lines .highlighted{position:relative}div[class*=language-].line-numbers-mode .highlight-lines .highlighted:before{content:" ";position:absolute;z-index:3;left:0;top:0;display:block;width:2.5rem;height:100%;background-color:rgba(0,0,0,.3)}div[class*=language-].line-numbers-mode pre{padding-left:3.5rem;vertical-align:middle}div[class*=language-].line-numbers-mode .line-numbers-wrapper{position:absolute;top:0;width:2.5rem;text-align:center;color:hsla(0,0%,49.8%,.5);padding:1.25rem 0;line-height:1.4}div[class*=language-].line-numbers-mode .line-numbers-wrapper br{-webkit-user-select:none;user-select:none}div[class*=language-].line-numbers-mode .line-numbers-wrapper .line-number{position:relative;z-index:4;-webkit-user-select:none;user-select:none;font-size:.85em}div[class*=language-].line-numbers-mode:after{content:"";position:absolute;z-index:2;top:0;left:0;width:2.5rem;height:100%;border-radius:6px 0 0 6px;border-right:1px solid var(--borderColor);background-color:var(--codeBg)}div[class~=language-js]:before{content:"js"}div[class~=language-ts]:before{content:"ts"}div[class~=language-html]:before{content:"html"}div[class~=language-md]:before{content:"md"}div[class~=language-vue]:before{content:"vue"}div[class~=language-css]:before{content:"css"}div[class~=language-sass]:before{content:"sass"}div[class~=language-scss]:before{content:"scss"}div[class~=language-less]:before{content:"less"}div[class~=language-stylus]:before{content:"stylus"}div[class~=language-go]:before{content:"go"}div[class~=language-java]:before{content:"java"}div[class~=language-c]:before{content:"c"}div[class~=language-sh]:before{content:"sh"}div[class~=language-yaml]:before{content:"yaml"}div[class~=language-py]:before{content:"py"}div[class~=language-docker]:before{content:"docker"}div[class~=language-dockerfile]:before{content:"dockerfile"}div[class~=language-makefile]:before{content:"makefile"}div[class~=language-javascript]:before{content:"js"}div[class~=language-typescript]:before{content:"ts"}div[class~=language-markup]:before{content:"html"}div[class~=language-markdown]:before{content:"md"}div[class~=language-json]:before{content:"json"}div[class~=language-ruby]:before{content:"rb"}div[class~=language-python]:before{content:"py"}div[class~=language-bash]:before{content:"sh"}div[class~=language-php]:before{content:"php"}.custom-block .custom-block-title{font-weight:600;margin-bottom:.2rem}.custom-block p{margin:0}.custom-block.danger,.custom-block.note,.custom-block.tip,.custom-block.warning{padding:.5rem 1.5rem;border-left-width:.5rem;border-left-style:solid;margin:1rem 0}.custom-block.tip{background-color:#f3f5f7;border-color:#42b983;color:#215d42}.custom-block.warning{background-color:#fff7d0;border-color:#e7c000;color:#6b5900}.custom-block.warning .custom-block-title{color:#b29400}.custom-block.warning a{color:var(--textColor)}.custom-block.danger{background-color:#ffe6e6;border-color:#c00;color:#4d0000}.custom-block.danger .custom-block-title{color:#900}.custom-block.danger a{color:var(--textColor)}.custom-block.note{background-color:#e8f5fa;border-color:#157bae;color:#0d4a68}.custom-block.right{color:var(--textColor);font-size:.9rem;text-align:right}.custom-block.theorem{margin:1rem 0;padding:.8rem 1.5rem;border-radius:2px;background-color:var(--customBlockBg)}.custom-block.theorem .title{font-weight:700;margin:.5rem 0}.custom-block.details{display:block;position:relative;border-radius:2px;margin:1em 0;padding:1.6em;background-color:var(--customBlockBg)}.custom-block.details p{margin:.8rem 0}.custom-block.details h4{margin-top:0}.custom-block.details figure:last-child,.custom-block.details p:last-child{margin-bottom:0;padding-bottom:0}.custom-block.details summary{outline:none;cursor:pointer}.custom-block.details summary:hover{color:#11a8cd}.theme-mode-dark .custom-block.warning{background-color:rgba(255,247,208,.2);color:#e7c000}.theme-mode-dark .custom-block.warning .custom-block-title{color:#ffdc2f}.theme-mode-dark .custom-block.tip{background-color:rgba(243,245,247,.2);color:#42b983}.theme-mode-dark .custom-block.danger{background-color:rgba(255,230,230,.4);color:maroon}.theme-mode-dark .custom-block.danger a{color:#11a8cd}.theme-mode-dark .custom-block.note{background-color:rgba(243,245,247,.2);color:#157bae}.arrow{display:inline-block;width:0;height:0}.arrow.up{border-bottom:6px solid #ccc}.arrow.down,.arrow.up{border-left:4px solid transparent;border-right:4px solid transparent}.arrow.down{border-top:6px solid #ccc}.arrow.right{border-left:6px solid #ccc}.arrow.left,.arrow.right{border-top:4px solid transparent;border-bottom:4px solid transparent}.arrow.left{border-right:6px solid #ccc}.theme-vdoing-content:not(.custom){max-width:860px}.table-of-contents .badge{vertical-align:middle}.center-container{text-align:center}.center-container>h1,.center-container>h2,.center-container>h3,.center-container>h4,.center-container>h5,.center-container>h6{margin-top:-3.1rem;padding-top:4.6rem;margin-bottom:0}.center-container>h1 a.header-anchor,.center-container>h2 a.header-anchor,.center-container>h3 a.header-anchor,.center-container>h4 a.header-anchor,.center-container>h5 a.header-anchor,.center-container>h6 a.header-anchor{float:none;padding-right:0;margin-left:-.9rem}.cardListContainer{margin:.7rem 0}.cardListContainer>:not(.card-list){display:none}.cardListContainer .card-list{margin:-.35rem;display:flex;flex-wrap:wrap;align-items:flex-start}.cardListContainer .card-list .card-item{width:calc(33.33333% - .7rem);margin:.35rem;background:var(--bodyBg);border-radius:3px;color:var(--textColor);display:flex;box-shadow:1px 1px 2px 0 rgba(0,0,0,.06);transition:all .4s}.cardListContainer .card-list .card-item:hover{text-decoration:none;box-shadow:0 10px 20px -10px var(--randomColor,rgba(0,0,0,.15));transform:translateY(-3px) scale(1.01)}.cardListContainer .card-list .card-item:hover img{box-shadow:3px 2px 7px rgba(0,0,0,.15)}.cardListContainer .card-list .card-item:hover div p{text-shadow:3px 2px 5px rgba(0,0,0,.15)}.cardListContainer .card-list .card-item img{width:60px;height:60px;border-radius:50%;border:2px solid #fff;margin:1rem 0 1rem 1rem;box-shadow:3px 2px 5px rgba(0,0,0,.08);transition:all .4s}.cardListContainer .card-list .card-item div{flex:1;display:inline-block;float:right;padding:1rem 0}.cardListContainer .card-list .card-item div p{margin:0;padding:0 1rem;transition:text-shadow .4s;text-align:center}.cardListContainer .card-list .card-item div .name{margin:.2rem 0 .3rem}.cardListContainer .card-list .card-item div .desc{font-size:.8rem;line-height:1.1rem;opacity:.8;margin-bottom:.2rem}.cardListContainer .card-list .card-item.row-1{width:calc(100% - .7rem)}.cardListContainer .card-list .card-item.row-1 img{margin-left:2rem}.cardListContainer .card-list .card-item.row-2{width:calc(50% - .7rem)}.cardListContainer .card-list .card-item.row-2 img{margin-left:1.5rem}.cardListContainer .card-list .card-item.row-3{width:calc(33.33333% - .7rem)}.cardListContainer .card-list .card-item.row-4{width:calc(25% - .7rem)}.cardImgListContainer{margin:1rem 0}.cardImgListContainer>:not(.card-list){display:none}.cardImgListContainer .card-list{margin:-.5rem;display:flex;flex-wrap:wrap;align-items:flex-start}.cardImgListContainer .card-list .card-item{width:calc(33.33333% - 1rem);margin:.5rem;background:var(--mainBg);border:1px solid rgba(0,0,0,.1);box-sizing:border-box;border-radius:3px;overflow:hidden;color:var(--textColor);box-shadow:2px 2px 10px rgba(0,0,0,.04);display:flex;flex-direction:column;justify-content:flex-start;align-items:stretch;align-content:stretch;transition:all .4s}.cardImgListContainer .card-list .card-item:hover{box-shadow:1px 1px 20px rgba(0,0,0,.1);transform:translateY(-3px)}.cardImgListContainer .card-list .card-item .box-img{overflow:hidden;position:relative;background:#eee}.cardImgListContainer .card-list .card-item .box-img img{display:block;width:100%;height:100%;transition:all .3s}.cardImgListContainer .card-list .card-item a{color:var(--textColor);transition:color .3s}.cardImgListContainer .card-list .card-item a:hover{text-decoration:none}.cardImgListContainer .card-list .card-item .box-info{padding:.8rem 1rem}.cardImgListContainer .card-list .card-item .box-info p{margin:0}.cardImgListContainer .card-list .card-item .box-info .desc{margin-top:.3rem;opacity:.8;font-size:.9rem;line-height:1.1rem;overflow:hidden;white-space:normal;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical}.cardImgListContainer .card-list .card-item .box-footer{overflow:hidden;padding:.8rem 1rem;border-top:1px solid rgba(0,0,0,.1)}.cardImgListContainer .card-list .card-item .box-footer img{width:1.8rem;height:1.8rem;border-radius:50%;float:left}.cardImgListContainer .card-list .card-item .box-footer span{line-height:1.8rem;float:left;margin-left:.6rem;font-size:.8rem}.cardImgListContainer .card-list .card-item.row-1{width:calc(100% - 1rem)}.cardImgListContainer .card-list .card-item.row-2{width:calc(50% - 1rem)}.cardImgListContainer .card-list .card-item.row-3{width:calc(33.33333% - 1rem)}.cardImgListContainer .card-list .card-item.row-4{width:calc(25% - 1rem)}.theme-mode-dark .cardImgListContainer .card-list .card-item,.theme-mode-dark .cardImgListContainer .card-list .card-item .box-footer{border-color:var(--borderColor)}@media (max-width:900px){.cardListContainer .card-list .card-item.row-4{width:calc(33.33333% - .7rem)}.cardImgListContainer .card-list .card-item.row-4{width:calc(33.33333% - 1rem)}}@media (max-width:720px){.cardListContainer .card-list .card-item.row-3,.cardListContainer .card-list .card-item.row-4{width:calc(50% - .7rem)}.cardListContainer .card-list .card-item.row-3 img,.cardListContainer .card-list .card-item.row-4 img{margin-left:1.5rem}.cardImgListContainer .card-list .card-item.row-3,.cardImgListContainer .card-list .card-item.row-4{width:calc(50% - 1rem)}}@media (max-width:500px){.cardListContainer .card-list .card-item.row-1,.cardListContainer .card-list .card-item.row-2,.cardListContainer .card-list .card-item.row-3,.cardListContainer .card-list .card-item.row-4{width:calc(100% - .7rem)}.cardListContainer .card-list .card-item.row-1 img,.cardListContainer .card-list .card-item.row-2 img,.cardListContainer .card-list .card-item.row-3 img,.cardListContainer .card-list .card-item.row-4 img{margin-left:1.5rem}.cardImgListContainer .card-list .card-item.row-1,.cardImgListContainer .card-list .card-item.row-2,.cardImgListContainer .card-list .card-item.row-3,.cardImgListContainer .card-list .card-item.row-4{width:calc(100% - 1rem)}}body,html{padding:0;margin:0}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-tap-highlight-color:transparent;font-size:16px;color:#2c3e50;background:var(--bodyBg)}a,button,input{outline:none;-webkit-tap-highlight-color:rgba(255,255,255,0);-webkit-focus-ring-color:transparent}@media (min-width:719px){::-webkit-scrollbar{width:6px;height:5px}::-webkit-scrollbar-track-piece{background-color:rgba(0,0,0,.15);-webkit-border-radius:3px}::-webkit-scrollbar-thumb:vertical{height:5px;background-color:rgba(0,0,0,.28);-webkit-border-radius:3px}::-webkit-scrollbar-thumb:horizontal{width:5px;background-color:rgba(0,0,0,.28);-webkit-border-radius:3px}}.card-box{border-radius:5px;background:var(--mainBg);box-shadow:0 0 4px 0 rgba(0,0,0,.1);transition:box-shadow .5s}.card-box:hover{box-shadow:0 1px 15px 0 rgba(0,0,0,.1)}@media (max-width:719px){.theme-style-line{margin-left:-1px;margin-right:-1px}}.theme-style-line .card-box{box-shadow:0 0;border:1px solid var(--borderColor)}.blur{-webkit-backdrop-filter:saturate(200%) blur(20px);backdrop-filter:saturate(200%) blur(20px)}.custom-page{min-height:calc(100vh - 3.6rem);padding-top:3.6rem;padding-bottom:.9rem}.custom-page .theme-vdoing-wrapper{margin:0 auto}body .search-box input{background-color:transparent;color:var(--textColor);border:1px solid var(--borderColor,#ccc)}@media (max-width:959px){body .search-box input{border-color:transparent}}.page{transition:padding .2s ease;padding-left:.8rem}.navbar{position:fixed;z-index:20;top:0;left:0;right:0;height:3.6rem;background-color:var(--blurBg);box-sizing:border-box;box-shadow:0 2px 5px rgba(0,0,0,.06)}.sidebar-mask{top:0;width:100vw;height:100vh}.sidebar-hover-trigger,.sidebar-mask{position:fixed;z-index:12;left:0;display:none}.sidebar-hover-trigger{top:8.1rem;bottom:0;width:24px}.sidebar{font-size:16px;background-color:var(--sidebarBg);width:18rem;position:fixed;z-index:13;margin:0;top:3.6rem;left:0;bottom:0;box-sizing:border-box;border-right:1px solid var(--borderColor);overflow-y:auto;transform:translateX(-100%);transition:transform .2s}@media (max-width:719px){.sidebar{background-color:var(--mainBg)}}.theme-vdoing-content:not(.custom){word-wrap:break-word}.theme-vdoing-content:not(.custom) a:hover{text-decoration:underline}.theme-vdoing-content:not(.custom) p.demo{padding:1rem 1.5rem;border:1px solid #ddd;border-radius:4px}.theme-vdoing-content:not(.custom) img{max-width:100%}.theme-vdoing-content.custom{padding:0;margin:0}.theme-vdoing-content.custom img{max-width:100%}a{font-weight:500;text-decoration:none}a,p a code{color:#11a8cd}p a code{font-weight:400}kbd{background:#eee;border:.15rem solid #ddd;border-bottom:.25rem solid #ddd;border-radius:.15rem;padding:0 .15em}blockquote{font-size:1rem;opacity:.75;border-left:.2rem solid hsla(0,0%,39.2%,.3);margin:1rem 0;padding:.25rem 0 .25rem 1rem}blockquote>p{margin:0}ol,ul{padding-left:1.2em}strong{font-weight:600}h1,h2,h3,h4,h5,h6{font-weight:600;line-height:1.25}.theme-vdoing-content:not(.custom)>h1,.theme-vdoing-content:not(.custom)>h2,.theme-vdoing-content:not(.custom)>h3,.theme-vdoing-content:not(.custom)>h4,.theme-vdoing-content:not(.custom)>h5,.theme-vdoing-content:not(.custom)>h6{margin-top:-3.1rem;padding-top:4.6rem;margin-bottom:0}.theme-vdoing-content:not(.custom)>h1:first-child,.theme-vdoing-content:not(.custom)>h2:first-child,.theme-vdoing-content:not(.custom)>h3:first-child,.theme-vdoing-content:not(.custom)>h4:first-child,.theme-vdoing-content:not(.custom)>h5:first-child,.theme-vdoing-content:not(.custom)>h6:first-child{margin-bottom:1rem}.theme-vdoing-content:not(.custom)>h1:first-child+.custom-block,.theme-vdoing-content:not(.custom)>h1:first-child+p,.theme-vdoing-content:not(.custom)>h1:first-child+pre,.theme-vdoing-content:not(.custom)>h2:first-child+.custom-block,.theme-vdoing-content:not(.custom)>h2:first-child+p,.theme-vdoing-content:not(.custom)>h2:first-child+pre,.theme-vdoing-content:not(.custom)>h3:first-child+.custom-block,.theme-vdoing-content:not(.custom)>h3:first-child+p,.theme-vdoing-content:not(.custom)>h3:first-child+pre,.theme-vdoing-content:not(.custom)>h4:first-child+.custom-block,.theme-vdoing-content:not(.custom)>h4:first-child+p,.theme-vdoing-content:not(.custom)>h4:first-child+pre,.theme-vdoing-content:not(.custom)>h5:first-child+.custom-block,.theme-vdoing-content:not(.custom)>h5:first-child+p,.theme-vdoing-content:not(.custom)>h5:first-child+pre,.theme-vdoing-content:not(.custom)>h6:first-child+.custom-block,.theme-vdoing-content:not(.custom)>h6:first-child+p,.theme-vdoing-content:not(.custom)>h6:first-child+pre{margin-top:2rem}h1:focus .header-anchor,h1:hover .header-anchor,h2:focus .header-anchor,h2:hover .header-anchor,h3:focus .header-anchor,h3:hover .header-anchor,h4:focus .header-anchor,h4:hover .header-anchor,h5:focus .header-anchor,h5:hover .header-anchor,h6:focus .header-anchor,h6:hover .header-anchor{opacity:1}.theme-vdoing-content:not(.custom)>.custom-block:first-child,.theme-vdoing-content:not(.custom)>p:first-child,.theme-vdoing-content:not(.custom)>pre:first-child{margin-top:2rem}h1{font-size:1.9rem}.theme-vdoing-content:not(.custom)>h1:first-child{display:none}h2{font-size:1.5rem;padding-bottom:.3rem;border-bottom:1px solid var(--borderColor)}h3{font-size:1.35rem}.page h4{font-size:1.25rem}.page h5{font-size:1.15rem}.page h6{font-size:1.05rem}a.header-anchor{font-size:.85em;float:left;margin-left:-.87em;padding-right:.23em;margin-top:.125em;opacity:0}a.header-anchor:focus,a.header-anchor:hover{text-decoration:none}.line-number,code,kbd{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}ol,p,ul{line-height:1.7}hr{border:0;border-top:1px solid var(--borderColor)}table{border-collapse:collapse;margin:1rem 0;overflow-x:auto;width:100%;display:inline-table}@media (max-width:719px){table{display:block}}tr{border-top:1px solid var(--borderColor)}tr:nth-child(2n){background-color:hsla(0,0%,58.8%,.1)}td,th{border:1px solid var(--borderColor);padding:.6em 1em}@media (max-width:719px){td,th{padding:.3em .5em}}td a,th a{word-break:break-all}.theme-container{color:var(--textColor);min-height:100vh}.theme-container.sidebar-open .sidebar-mask{display:block}.theme-container.no-navbar .theme-vdoing-content:not(.custom)>h1,.theme-container.no-navbar h2,.theme-container.no-navbar h3,.theme-container.no-navbar h4,.theme-container.no-navbar h5,.theme-container.no-navbar h6{margin-top:1.5rem;padding-top:0}.theme-container.no-navbar .sidebar{top:0}@media (min-width:720px){.theme-container.no-sidebar .sidebar{display:none}.theme-container.no-sidebar .page{padding-left:0}}@media (max-width:959px){.sidebar{font-size:15px}}@media (max-width:719px){.sidebar{width:17.099999999999998rem}}@media (min-width:720px) and (max-width:959px){.sidebar{width:16.2rem}.theme-container.sidebar-open .page{padding-left:17rem!important}}@media (max-width:719px){.sidebar{top:0;height:100vh;padding-top:3.6rem;transform:translateX(-100%);transition:transform .2s ease}.page{padding-left:0}.theme-container.sidebar-open .sidebar{transform:translateX(0)}.theme-container.sidebar-open .sidebar-mask{display:block}.theme-container.no-navbar .sidebar{padding-top:0}}@media (max-width:419px){h1{font-size:1.9rem}.theme-vdoing-content div[class*=language-]{margin:.85rem -1.5rem;border-radius:0}}@media (min-width:720px){.theme-container .sidebar-hover-trigger{display:block}.theme-container .sidebar-hover-trigger:hover~.sidebar,.theme-container:not(.sidebar-open) .sidebar-hover-trigger~.sidebar:hover{transform:translateX(0);z-index:100}.theme-container.sidebar-open .sidebar-mask{display:none}.theme-container.sidebar-open .sidebar{transform:translateX(0)}.theme-container.sidebar-open .sidebar-button{left:18rem}.theme-container.sidebar-open .page{padding-left:18.8rem;padding-right:.8rem}.theme-container.sidebar-open .sidebar-hover-trigger{display:none}.theme-container.have-rightmenu .page{padding-right:250px}.theme-container.no-sidebar .page{padding-left:0!important}.theme-container.no-sidebar .sidebar-hover-trigger{display:none}.theme-container.hide-navbar .sidebar-hover-trigger{top:4.5rem}.theme-container.hide-navbar .sidebar{top:0}.theme-container.no-sidebar .sidebar-button{display:none}}@media print{.buttons,.navbar,.sidebar{display:none}.page{padding-top:0!important}}@media (min-width:720px) and (max-width:959px){.theme-container.sidebar-open:not(.on-sidebar) .sidebar-button{left:12.6rem}}.home-wrapper .banner .banner-conent .hero h1{font-size:2.8rem!important}table{width:auto}.card-box,.page>:not(.footer){box-shadow:none!important}@media (min-width:940px){.page{padding-top:3.6rem!important}}.home-wrapper .banner .banner-conent{padding:0 2.9rem;box-sizing:border-box}.home-wrapper .banner .slide-banner .slide-banner-wrapper .slide-item a h2{margin-top:2rem;font-size:1.2rem!important}.home-wrapper .banner .slide-banner .slide-banner-wrapper .slide-item a p{padding:0 1rem}.gt-container .gt-ico-tip:after{content:"。( Win + . ) or ( ⌃ + ⌘ + ␣ ) open Emoji";color:#999}.gt-container .gt-meta{border-color:var(--borderColor)!important}.gt-container .gt-comments-null{color:var(--textColor);opacity:.5}.gt-container .gt-header-textarea{color:var(--textColor);background:hsla(0,0%,70.6%,.1)!important}.gt-container .gt-btn{border-color:#11a8cd!important;background-color:#11a8cd!important}.gt-container .gt-btn-preview{background-color:hsla(0,0%,100%,0)!important;color:#11a8cd!important}.gt-container a{color:#11a8cd!important}.gt-container .gt-svg svg{fill:#11a8cd!important}.gt-container .gt-comment-admin .gt-comment-content,.gt-container .gt-comment-content{background-color:hsla(0,0%,58.8%,.1)!important}.gt-container .gt-comment-admin .gt-comment-content:hover,.gt-container .gt-comment-content:hover{box-shadow:0 0 25px hsla(0,0%,58.8%,.5)!important}.gt-container .gt-comment-admin .gt-comment-content .gt-comment-body,.gt-container .gt-comment-content .gt-comment-body{color:var(--textColor)!important}.qq{position:relative}.qq:after{content:"可撩";background:#11a8cd;color:#fff;padding:0 5px;border-radius:10px;font-size:12px;position:absolute;top:-4px;right:-35px;transform:scale(.85)}body .vuepress-plugin-demo-block__wrapper,body .vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__display{border-color:hsla(0,0%,62.7%,.3)}body .vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer:hover .vuepress-plugin-demo-block__expand:before{border-top-color:#11a8cd!important;border-bottom-color:#11a8cd!important}body .vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer:hover svg{fill:#11a8cd!important}.suggestions{overflow:auto;max-height:calc(100vh - 6rem)}@media (max-width:719px){.suggestions{width:90vw;min-width:90vw!important;margin-right:-20px}}.suggestions .highlight{color:#11a8cd;font-weight:700}#nprogress{pointer-events:none}#nprogress .bar{background:#11a8cd;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #11a8cd,0 0 5px #11a8cd;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border-color:#11a8cd transparent transparent #11a8cd;border-style:solid;border-width:2px;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.icon.outbound{color:#aaa;display:inline-block;vertical-align:middle;position:relative;top:-1px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.theme-mode-light[data-v-439bb2a8]{--bodyBg:#f4f4f4;--customBlockBg:#f1f1f1;--textColor:#00323c;--borderColor:rgba(0,0,0,0.12)}.theme-mode-dark[data-v-439bb2a8]{--bodyBg:#27272b;--customBlockBg:#27272b;--textColor:#9b9baa;--borderColor:#30363d}.theme-mode-read[data-v-439bb2a8]{--bodyBg:#ececcc;--customBlockBg:#ececcc;--textColor:#704214;--textLightenColor:#963}.theme-style-line.theme-mode-light[data-v-439bb2a8]{--bodyBg:#fff}.theme-style-line.theme-mode-dark[data-v-439bb2a8]{--bodyBg:#1e1e22}.theme-style-line.theme-mode-read[data-v-439bb2a8]{--bodyBg:#f5f5d5}.theme-mode-light[data-v-439bb2a8]{--bodyBg:#fff;--mainBg:#fff;--sidebarBg:hsla(0,0%,100%,0.8);--blurBg:hsla(0,0%,100%,0.9);--textColor:#004050;--textLightenColor:#0085ad;--borderColor:rgba(0,0,0,0.15);--codeBg:#f6f6f6;--codeColor:#525252}.theme-mode-light code[class*=language-][data-v-439bb2a8],.theme-mode-light pre[class*=language-][data-v-439bb2a8]{color:#000;background:none;text-shadow:0 1px #fff;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-light code[class*=language-][data-v-439bb2a8]::-moz-selection,.theme-mode-light code[class*=language-][data-v-439bb2a8] ::-moz-selection,.theme-mode-light pre[class*=language-][data-v-439bb2a8]::-moz-selection,.theme-mode-light pre[class*=language-][data-v-439bb2a8] ::-moz-selection{text-shadow:none;background:#b3d4fc}.theme-mode-light code[class*=language-][data-v-439bb2a8]::selection,.theme-mode-light code[class*=language-][data-v-439bb2a8] ::selection,.theme-mode-light pre[class*=language-][data-v-439bb2a8]::selection,.theme-mode-light pre[class*=language-][data-v-439bb2a8] ::selection{text-shadow:none;background:#b3d4fc}@media print{.theme-mode-light code[class*=language-][data-v-439bb2a8],.theme-mode-light pre[class*=language-][data-v-439bb2a8]{text-shadow:none}}.theme-mode-light pre[class*=language-][data-v-439bb2a8]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-light :not(pre)>code[class*=language-][data-v-439bb2a8],.theme-mode-light pre[class*=language-][data-v-439bb2a8]{background:#f5f2f0}.theme-mode-light :not(pre)>code[class*=language-][data-v-439bb2a8]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-light .token.cdata[data-v-439bb2a8],.theme-mode-light .token.comment[data-v-439bb2a8],.theme-mode-light .token.doctype[data-v-439bb2a8],.theme-mode-light .token.prolog[data-v-439bb2a8]{color:#708090}.theme-mode-light .token.punctuation[data-v-439bb2a8]{color:#999}.theme-mode-light .namespace[data-v-439bb2a8]{opacity:.7}.theme-mode-light .token.boolean[data-v-439bb2a8],.theme-mode-light .token.constant[data-v-439bb2a8],.theme-mode-light .token.deleted[data-v-439bb2a8],.theme-mode-light .token.number[data-v-439bb2a8],.theme-mode-light .token.property[data-v-439bb2a8],.theme-mode-light .token.symbol[data-v-439bb2a8],.theme-mode-light .token.tag[data-v-439bb2a8]{color:#905}.theme-mode-light .token.attr-name[data-v-439bb2a8],.theme-mode-light .token.builtin[data-v-439bb2a8],.theme-mode-light .token.char[data-v-439bb2a8],.theme-mode-light .token.inserted[data-v-439bb2a8],.theme-mode-light .token.selector[data-v-439bb2a8],.theme-mode-light .token.string[data-v-439bb2a8]{color:#690}.theme-mode-light .language-css .token.string[data-v-439bb2a8],.theme-mode-light .style .token.string[data-v-439bb2a8],.theme-mode-light .token.entity[data-v-439bb2a8],.theme-mode-light .token.operator[data-v-439bb2a8],.theme-mode-light .token.url[data-v-439bb2a8]{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.theme-mode-light .token.atrule[data-v-439bb2a8],.theme-mode-light .token.attr-value[data-v-439bb2a8],.theme-mode-light .token.keyword[data-v-439bb2a8]{color:#07a}.theme-mode-light .token.class-name[data-v-439bb2a8],.theme-mode-light .token.function[data-v-439bb2a8]{color:#dd4a68}.theme-mode-light .token.important[data-v-439bb2a8],.theme-mode-light .token.regex[data-v-439bb2a8],.theme-mode-light .token.variable[data-v-439bb2a8]{color:#e90}.theme-mode-light .token.bold[data-v-439bb2a8],.theme-mode-light .token.important[data-v-439bb2a8]{font-weight:700}.theme-mode-light .token.italic[data-v-439bb2a8]{font-style:italic}.theme-mode-light .token.entity[data-v-439bb2a8]{cursor:help}.theme-mode-light div[class*=language-] .highlight-lines .highlighted[data-v-439bb2a8],.theme-mode-light div[class*=language-].line-numbers-mode .highlight-lines .highlighted[data-v-439bb2a8]:before{background-color:hsla(0,0%,78.4%,.4)}.theme-mode-dark[data-v-439bb2a8]{--bodyBg:#1e1e22;--mainBg:#1e1e22;--sidebarBg:rgba(30,30,34,0.8);--blurBg:rgba(30,30,34,0.8);--textColor:#8c8c96;--textLightenColor:#0085ad;--borderColor:#2c2c3a;--codeBg:#252526;--codeColor:#fff}.theme-mode-dark code[class*=language-][data-v-439bb2a8],.theme-mode-dark pre[class*=language-][data-v-439bb2a8]{color:#ccc;background:none;text-shadow:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-dark pre[class*=language-][data-v-439bb2a8]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-dark :not(pre)>code[class*=language-][data-v-439bb2a8],.theme-mode-dark pre[class*=language-][data-v-439bb2a8]{background:#2d2d2d}.theme-mode-dark :not(pre)>code[class*=language-][data-v-439bb2a8]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-dark .token.block-comment[data-v-439bb2a8],.theme-mode-dark .token.cdata[data-v-439bb2a8],.theme-mode-dark .token.comment[data-v-439bb2a8],.theme-mode-dark .token.doctype[data-v-439bb2a8],.theme-mode-dark .token.prolog[data-v-439bb2a8]{color:#999}.theme-mode-dark .token.punctuation[data-v-439bb2a8]{color:#ccc}.theme-mode-dark .token.attr-name[data-v-439bb2a8],.theme-mode-dark .token.deleted[data-v-439bb2a8],.theme-mode-dark .token.namespace[data-v-439bb2a8],.theme-mode-dark .token.tag[data-v-439bb2a8]{color:#e2777a}.theme-mode-dark .token.function-name[data-v-439bb2a8]{color:#6196cc}.theme-mode-dark .token.boolean[data-v-439bb2a8],.theme-mode-dark .token.function[data-v-439bb2a8],.theme-mode-dark .token.number[data-v-439bb2a8]{color:#f08d49}.theme-mode-dark .token.class-name[data-v-439bb2a8],.theme-mode-dark .token.constant[data-v-439bb2a8],.theme-mode-dark .token.property[data-v-439bb2a8],.theme-mode-dark .token.symbol[data-v-439bb2a8]{color:#f8c555}.theme-mode-dark .token.atrule[data-v-439bb2a8],.theme-mode-dark .token.builtin[data-v-439bb2a8],.theme-mode-dark .token.important[data-v-439bb2a8],.theme-mode-dark .token.keyword[data-v-439bb2a8],.theme-mode-dark .token.selector[data-v-439bb2a8]{color:#cc99cd}.theme-mode-dark .token.attr-value[data-v-439bb2a8],.theme-mode-dark .token.char[data-v-439bb2a8],.theme-mode-dark .token.regex[data-v-439bb2a8],.theme-mode-dark .token.string[data-v-439bb2a8],.theme-mode-dark .token.variable[data-v-439bb2a8]{color:#7ec699}.theme-mode-dark .token.entity[data-v-439bb2a8],.theme-mode-dark .token.operator[data-v-439bb2a8],.theme-mode-dark .token.url[data-v-439bb2a8]{color:#67cdcc}.theme-mode-dark .language-css .token.string[data-v-439bb2a8],.theme-mode-dark .style .token.string[data-v-439bb2a8],.theme-mode-dark .token.entity[data-v-439bb2a8],.theme-mode-dark .token.operator[data-v-439bb2a8],.theme-mode-dark .token.url[data-v-439bb2a8]{background:none}.theme-mode-dark .token.bold[data-v-439bb2a8],.theme-mode-dark .token.important[data-v-439bb2a8]{font-weight:700}.theme-mode-dark .token.italic[data-v-439bb2a8]{font-style:italic}.theme-mode-dark .token.entity[data-v-439bb2a8]{cursor:help}.theme-mode-dark .token.inserted[data-v-439bb2a8]{color:green}.theme-mode-read[data-v-439bb2a8]{--bodyBg:#f5f5d5;--mainBg:#f5f5d5;--sidebarBg:rgba(245,245,213,0.8);--blurBg:rgba(245,245,213,0.9);--textColor:#004050;--textLightenColor:#0085ad;--borderColor:rgba(0,0,0,0.15);--codeBg:#282c34;--codeColor:#fff}.theme-mode-read code[class*=language-][data-v-439bb2a8],.theme-mode-read pre[class*=language-][data-v-439bb2a8]{color:#ccc;background:none;text-shadow:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-read pre[class*=language-][data-v-439bb2a8]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-read :not(pre)>code[class*=language-][data-v-439bb2a8],.theme-mode-read pre[class*=language-][data-v-439bb2a8]{background:#2d2d2d}.theme-mode-read :not(pre)>code[class*=language-][data-v-439bb2a8]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-read .token.block-comment[data-v-439bb2a8],.theme-mode-read .token.cdata[data-v-439bb2a8],.theme-mode-read .token.comment[data-v-439bb2a8],.theme-mode-read .token.doctype[data-v-439bb2a8],.theme-mode-read .token.prolog[data-v-439bb2a8]{color:#999}.theme-mode-read .token.punctuation[data-v-439bb2a8]{color:#ccc}.theme-mode-read .token.attr-name[data-v-439bb2a8],.theme-mode-read .token.deleted[data-v-439bb2a8],.theme-mode-read .token.namespace[data-v-439bb2a8],.theme-mode-read .token.tag[data-v-439bb2a8]{color:#e2777a}.theme-mode-read .token.function-name[data-v-439bb2a8]{color:#6196cc}.theme-mode-read .token.boolean[data-v-439bb2a8],.theme-mode-read .token.function[data-v-439bb2a8],.theme-mode-read .token.number[data-v-439bb2a8]{color:#f08d49}.theme-mode-read .token.class-name[data-v-439bb2a8],.theme-mode-read .token.constant[data-v-439bb2a8],.theme-mode-read .token.property[data-v-439bb2a8],.theme-mode-read .token.symbol[data-v-439bb2a8]{color:#f8c555}.theme-mode-read .token.atrule[data-v-439bb2a8],.theme-mode-read .token.builtin[data-v-439bb2a8],.theme-mode-read .token.important[data-v-439bb2a8],.theme-mode-read .token.keyword[data-v-439bb2a8],.theme-mode-read .token.selector[data-v-439bb2a8]{color:#cc99cd}.theme-mode-read .token.attr-value[data-v-439bb2a8],.theme-mode-read .token.char[data-v-439bb2a8],.theme-mode-read .token.regex[data-v-439bb2a8],.theme-mode-read .token.string[data-v-439bb2a8],.theme-mode-read .token.variable[data-v-439bb2a8]{color:#7ec699}.theme-mode-read .token.entity[data-v-439bb2a8],.theme-mode-read .token.operator[data-v-439bb2a8],.theme-mode-read .token.url[data-v-439bb2a8]{color:#67cdcc}.theme-mode-read .language-css .token.string[data-v-439bb2a8],.theme-mode-read .style .token.string[data-v-439bb2a8],.theme-mode-read .token.entity[data-v-439bb2a8],.theme-mode-read .token.operator[data-v-439bb2a8],.theme-mode-read .token.url[data-v-439bb2a8]{background:none}.theme-mode-read .token.bold[data-v-439bb2a8],.theme-mode-read .token.important[data-v-439bb2a8]{font-weight:700}.theme-mode-read .token.italic[data-v-439bb2a8]{font-style:italic}.theme-mode-read .token.entity[data-v-439bb2a8]{cursor:help}.theme-mode-read .token.inserted[data-v-439bb2a8]{color:green}.theme-vdoing-content[data-v-439bb2a8]{margin:3rem auto;padding:1.5rem}.theme-vdoing-content span[data-v-439bb2a8]{font-size:6rem;color:#11a8cd}.main-wrapper{margin:1.5rem auto 0;max-width:1100px;padding:0 .9rem;box-sizing:border-box;position:relative;display:flex}.main-wrapper .main-left{flex:1}.main-wrapper .main-left .theme-vdoing-content.card-box{padding:1rem 1.5rem;margin-bottom:.9rem}.main-wrapper .main-left .home-content{padding:1rem 1.5rem 0}.main-wrapper .main-right>*{width:245px;box-sizing:border-box}@media (max-width:900px){.main-wrapper .main-right>*{width:235px}}.main-wrapper .main-right .card-box{margin:0 0 .8rem .8rem;padding-top:.95rem;padding-bottom:.95rem}@media (max-width:719px){.main-wrapper{margin:.9rem 0;padding:0;display:block}.main-wrapper .main-left{width:100%}.main-wrapper .main-left .post-list{margin-bottom:3rem}.main-wrapper .main-left .post-list .post{border-radius:0}.main-wrapper .main-left .pagination{margin-bottom:3rem}.main-wrapper .main-right .blogger-wrapper{display:none}.main-wrapper .main-right .card-box{margin:0 0 .9rem;border-radius:0;width:100%}.theme-style-line .main-wrapper .main-right .card-box{margin:-1px 0 0}}.post-list{margin-bottom:3rem}.post-list .post{position:relative;padding:1rem 1.5rem;margin-bottom:.8rem;transition:all .3s}.post-list .post:last-child{border-bottom:none}.post-list .post.post-leave-active{display:none}.post-list .post.post-enter{opacity:0;transform:translateX(-20px)}.post-list .post:before{position:absolute;top:-1px;right:0;font-size:2.5rem;color:#ff5722;opacity:.85}.post-list .post .title-wrapper a{color:var(--textColor)}.post-list .post .title-wrapper a:hover{color:#11a8cd}.post-list .post .title-wrapper h2{margin:.5rem 0;font-size:1.4rem;border:none}.post-list .post .title-wrapper h2 .title-tag{height:1.2rem;line-height:1.2rem;border:1px solid #ff5722;color:#ff5722;font-size:.8rem;padding:0 .35rem;border-radius:.2rem;margin-left:0;transform:translateY(-.15rem);display:inline-block}.post-list .post .title-wrapper h2 a{display:block}@media (max-width:719px){.post-list .post .title-wrapper h2 a{font-weight:400}}.post-list .post .title-wrapper .article-info>a,.post-list .post .title-wrapper .article-info>span{opacity:.7;font-size:.8rem;margin-right:1rem;cursor:pointer}.post-list .post .title-wrapper .article-info>a:before,.post-list .post .title-wrapper .article-info>span:before{margin-right:.3rem}.post-list .post .title-wrapper .article-info>a a,.post-list .post .title-wrapper .article-info>span a{margin:0}.post-list .post .title-wrapper .article-info>a a:not(:first-child):before,.post-list .post .title-wrapper .article-info>span a:not(:first-child):before{content:"/"}.post-list .post .title-wrapper .article-info .tags a:not(:first-child):before{content:"、"}.post-list .post .excerpt-wrapper{border-top:1px solid var(--borderColor);margin:.5rem 0;overflow:hidden}.post-list .post .excerpt-wrapper .excerpt{margin-bottom:.3rem;font-size:.92rem}.post-list .post .excerpt-wrapper .excerpt h1,.post-list .post .excerpt-wrapper .excerpt h2,.post-list .post .excerpt-wrapper .excerpt h3{display:none}.post-list .post .excerpt-wrapper .excerpt img{max-height:280px;max-width:100%!important;margin:0 auto}.post-list .post .excerpt-wrapper .readmore{float:right;margin-right:1rem;line-height:1rem}.post-list .post .excerpt-wrapper .readmore:before{float:right;font-size:.8rem;margin:.1rem 0 0 .2rem}.theme-style-line .post-list{border:1px solid var(--borderColor);border-bottom:none;border-radius:5px;overflow:hidden}.theme-style-line .post-list .post{margin-bottom:0;border:none;border-bottom:1px solid var(--borderColor);border-radius:0}.article-list{padding:1rem 2rem}@media (max-width:959px){.article-list{padding:1rem 1.5rem}}.article-list.no-article-list{display:none}.article-list .article-title{border-bottom:1px solid var(--borderColor);font-size:1.3rem;padding:1rem}.article-list .article-title a{font-size:1.2rem;color:var(--textColor);opacity:.9}.article-list .article-title a:before{margin-right:.4rem;font-size:1.1rem}.article-list .article-wrapper{overflow:hidden}.article-list .article-wrapper dl{border-bottom:1px dotted var(--borderColor);float:left;display:flex;padding:8px 0;margin:0;height:45px;width:100%}.article-list .article-wrapper dl dd{font-size:1.1rem;color:#f17229;width:50px;text-align:center;margin:0;line-height:45px}.article-list .article-wrapper dl dt{flex:1;display:flex}.article-list .article-wrapper dl dt a{color:var(--textColor);flex:1;display:flex;height:45px;align-items:center;font-weight:400}.article-list .article-wrapper dl dt a div{overflow:hidden;white-space:normal;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.article-list .article-wrapper dl dt a div .title-tag{border:1px solid #ff5722;color:#ff5722;font-size:.8rem;padding:0 .35rem;border-radius:.2rem;margin-left:0;transform:translateY(-.05rem);display:inline-block}.article-list .article-wrapper dl dt a:hover{text-decoration:underline}.article-list .article-wrapper dl dt a.more{color:#11a8cd}.article-list .article-wrapper dl dt .date{width:50px;margin-right:15px;color:#999;text-align:right;font-size:.9rem;line-height:45px}.pagination{position:relative;height:60px;text-align:center}@media (max-width:720px){.pagination{margin-left:1px;margin-right:1px}}.pagination span{line-height:1rem;opacity:.9;cursor:pointer}.pagination span:hover{color:#11a8cd}.pagination span.ellipsis{opacity:.5}.pagination span.ellipsis:before{content:"...";font-size:1.2rem}@media (any-hover:hover){.pagination span.ellipsis.ell-two:hover:before{content:"«"}.pagination span.ellipsis.ell-four:hover:before{content:"»"}}.pagination>span{position:absolute;top:0;padding:1rem 1.2rem;font-size:.95rem}.pagination>span:before{font-size:.4rem}.pagination>span.disabled{color:hsla(0,0%,49%,.5)}.pagination>span.prev{left:0}.pagination>span.prev:before{margin-right:.3rem}.pagination>span.next{right:0}.pagination>span.next:before{float:right;margin-left:.3rem}.pagination>span p{display:inline;line-height:.95rem}.pagination .pagination-list span{display:inline-block;width:2.5rem;height:2.5rem;line-height:2.5rem;margin:.3rem}.pagination .pagination-list span.active{background:#11a8cd;color:var(--mainBg)}@media (max-width:800px){.pagination>span{padding:1rem 1.5rem}.pagination>span p{display:none}}@media (max-width:719px){.pagination>span{padding:.9rem 1.5rem}.pagination .pagination-list span{width:2.3rem;height:2.3rem;line-height:2.3rem;margin:.25rem}}@media (max-width:390px){.pagination>span{padding:.8rem 1.3rem}.pagination .pagination-list span{width:2rem;height:2rem;line-height:2rem;margin:.3rem .1rem .1rem}}.blogger-wrapper{height:auto;display:inline-table;padding-top:0!important;overflow:hidden}.blogger-wrapper .avatar{width:100%;overflow:hidden}.blogger-wrapper .avatar img{width:100%;height:100%}.blogger-wrapper .icons{border-top:none;height:35px;line-height:35px}.blogger-wrapper .icons a{font-size:20px;width:33%;color:var(--textColor);display:block;float:left;text-align:center;opacity:.8}.blogger-wrapper .icons a:hover{color:#11a8cd}.blogger-wrapper .blogger{padding:.3rem .95rem 0}.blogger-wrapper .blogger .name{font-size:1.3rem;display:block;margin-bottom:6px}.blogger-wrapper .blogger .slogan{color:var(--textColor)}.categories-wrapper .title{color:var(--textColor);opacity:.9;font-size:1.2rem;padding:0 .95rem}.categories-wrapper .title:before{margin-right:.3rem}.categories-wrapper .categories{margin-top:.6rem}.categories-wrapper .categories a{display:block;padding:8px .95rem 7px;color:var(--textColor);opacity:.8;font-size:.95rem;line-height:.95rem;position:relative;transition:all .2s;border-left:2px solid transparent;margin-top:-1px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media (max-width:719px){.categories-wrapper .categories a{font-weight:400}}.categories-wrapper .categories a:not(.active):hover{color:#11a8cd;background:#f8f8f8;border-color:#11a8cd}.categories-wrapper .categories a:not(.active):hover span{opacity:.8}.categories-wrapper .categories a span{float:right;background-color:var(--textColor);color:var(--mainBg);border-radius:8px;padding:0 .13rem;min-width:1rem;height:1rem;line-height:1rem;font-size:.6rem;text-align:center;opacity:.6;transition:opacity .3s}.categories-wrapper .categories a.active{background:#11a8cd;color:var(--mainBg);padding-left:.8rem;border-radius:1px;border-color:transparent}.theme-mode-dark .categories-wrapper .categories a:not(.active):hover,.theme-mode-read .categories-wrapper .categories a:not(.active):hover{background:var(--customBlockBg)}.tags-wrapper{padding:0 .95rem}.tags-wrapper .title{color:var(--textColor);opacity:.9;font-size:1.2rem}.tags-wrapper .title:before{margin-right:.3rem}.tags-wrapper .tags{text-align:justify;padding:.8rem .5rem .5rem;margin:0 -.5rem -.5rem}.tags-wrapper .tags a{opacity:.8;display:inline-block;padding:.2rem .4rem;transition:all .4s;background-color:var(--textColor);color:var(--mainBg);border-radius:3px;margin:0 .3rem .5rem 0;min-width:2rem;height:1rem;line-height:1rem;font-size:.8rem;text-align:center}@media (max-width:719px){.tags-wrapper .tags a{font-weight:400}}.tags-wrapper .tags a:hover{opacity:1;transform:scale(1.1)}.tags-wrapper .tags a.active{box-shadow:0 5px 10px -5px var(--randomColor,rgba(0,0,0,.15));transform:scale(1.22);opacity:1}.tags-wrapper .tags a.active:hover{text-decoration:none}.theme-mode-light[data-v-7d2bb426]{--bodyBg:#f4f4f4;--customBlockBg:#f1f1f1;--textColor:#00323c;--borderColor:rgba(0,0,0,0.12)}.theme-mode-dark[data-v-7d2bb426]{--bodyBg:#27272b;--customBlockBg:#27272b;--textColor:#9b9baa;--borderColor:#30363d}.theme-mode-read[data-v-7d2bb426]{--bodyBg:#ececcc;--customBlockBg:#ececcc;--textColor:#704214;--textLightenColor:#963}.theme-style-line.theme-mode-light[data-v-7d2bb426]{--bodyBg:#fff}.theme-style-line.theme-mode-dark[data-v-7d2bb426]{--bodyBg:#1e1e22}.theme-style-line.theme-mode-read[data-v-7d2bb426]{--bodyBg:#f5f5d5}.theme-mode-light[data-v-7d2bb426]{--bodyBg:#fff;--mainBg:#fff;--sidebarBg:hsla(0,0%,100%,0.8);--blurBg:hsla(0,0%,100%,0.9);--textColor:#004050;--textLightenColor:#0085ad;--borderColor:rgba(0,0,0,0.15);--codeBg:#f6f6f6;--codeColor:#525252}.theme-mode-light code[class*=language-][data-v-7d2bb426],.theme-mode-light pre[class*=language-][data-v-7d2bb426]{color:#000;background:none;text-shadow:0 1px #fff;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-light code[class*=language-][data-v-7d2bb426]::-moz-selection,.theme-mode-light code[class*=language-][data-v-7d2bb426] ::-moz-selection,.theme-mode-light pre[class*=language-][data-v-7d2bb426]::-moz-selection,.theme-mode-light pre[class*=language-][data-v-7d2bb426] ::-moz-selection{text-shadow:none;background:#b3d4fc}.theme-mode-light code[class*=language-][data-v-7d2bb426]::selection,.theme-mode-light code[class*=language-][data-v-7d2bb426] ::selection,.theme-mode-light pre[class*=language-][data-v-7d2bb426]::selection,.theme-mode-light pre[class*=language-][data-v-7d2bb426] ::selection{text-shadow:none;background:#b3d4fc}@media print{.theme-mode-light code[class*=language-][data-v-7d2bb426],.theme-mode-light pre[class*=language-][data-v-7d2bb426]{text-shadow:none}}.theme-mode-light pre[class*=language-][data-v-7d2bb426]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-light :not(pre)>code[class*=language-][data-v-7d2bb426],.theme-mode-light pre[class*=language-][data-v-7d2bb426]{background:#f5f2f0}.theme-mode-light :not(pre)>code[class*=language-][data-v-7d2bb426]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-light .token.cdata[data-v-7d2bb426],.theme-mode-light .token.comment[data-v-7d2bb426],.theme-mode-light .token.doctype[data-v-7d2bb426],.theme-mode-light .token.prolog[data-v-7d2bb426]{color:#708090}.theme-mode-light .token.punctuation[data-v-7d2bb426]{color:#999}.theme-mode-light .namespace[data-v-7d2bb426]{opacity:.7}.theme-mode-light .token.boolean[data-v-7d2bb426],.theme-mode-light .token.constant[data-v-7d2bb426],.theme-mode-light .token.deleted[data-v-7d2bb426],.theme-mode-light .token.number[data-v-7d2bb426],.theme-mode-light .token.property[data-v-7d2bb426],.theme-mode-light .token.symbol[data-v-7d2bb426],.theme-mode-light .token.tag[data-v-7d2bb426]{color:#905}.theme-mode-light .token.attr-name[data-v-7d2bb426],.theme-mode-light .token.builtin[data-v-7d2bb426],.theme-mode-light .token.char[data-v-7d2bb426],.theme-mode-light .token.inserted[data-v-7d2bb426],.theme-mode-light .token.selector[data-v-7d2bb426],.theme-mode-light .token.string[data-v-7d2bb426]{color:#690}.theme-mode-light .language-css .token.string[data-v-7d2bb426],.theme-mode-light .style .token.string[data-v-7d2bb426],.theme-mode-light .token.entity[data-v-7d2bb426],.theme-mode-light .token.operator[data-v-7d2bb426],.theme-mode-light .token.url[data-v-7d2bb426]{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.theme-mode-light .token.atrule[data-v-7d2bb426],.theme-mode-light .token.attr-value[data-v-7d2bb426],.theme-mode-light .token.keyword[data-v-7d2bb426]{color:#07a}.theme-mode-light .token.class-name[data-v-7d2bb426],.theme-mode-light .token.function[data-v-7d2bb426]{color:#dd4a68}.theme-mode-light .token.important[data-v-7d2bb426],.theme-mode-light .token.regex[data-v-7d2bb426],.theme-mode-light .token.variable[data-v-7d2bb426]{color:#e90}.theme-mode-light .token.bold[data-v-7d2bb426],.theme-mode-light .token.important[data-v-7d2bb426]{font-weight:700}.theme-mode-light .token.italic[data-v-7d2bb426]{font-style:italic}.theme-mode-light .token.entity[data-v-7d2bb426]{cursor:help}.theme-mode-light div[class*=language-] .highlight-lines .highlighted[data-v-7d2bb426],.theme-mode-light div[class*=language-].line-numbers-mode .highlight-lines .highlighted[data-v-7d2bb426]:before{background-color:hsla(0,0%,78.4%,.4)}.theme-mode-dark[data-v-7d2bb426]{--bodyBg:#1e1e22;--mainBg:#1e1e22;--sidebarBg:rgba(30,30,34,0.8);--blurBg:rgba(30,30,34,0.8);--textColor:#8c8c96;--textLightenColor:#0085ad;--borderColor:#2c2c3a;--codeBg:#252526;--codeColor:#fff}.theme-mode-dark code[class*=language-][data-v-7d2bb426],.theme-mode-dark pre[class*=language-][data-v-7d2bb426]{color:#ccc;background:none;text-shadow:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-dark pre[class*=language-][data-v-7d2bb426]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-dark :not(pre)>code[class*=language-][data-v-7d2bb426],.theme-mode-dark pre[class*=language-][data-v-7d2bb426]{background:#2d2d2d}.theme-mode-dark :not(pre)>code[class*=language-][data-v-7d2bb426]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-dark .token.block-comment[data-v-7d2bb426],.theme-mode-dark .token.cdata[data-v-7d2bb426],.theme-mode-dark .token.comment[data-v-7d2bb426],.theme-mode-dark .token.doctype[data-v-7d2bb426],.theme-mode-dark .token.prolog[data-v-7d2bb426]{color:#999}.theme-mode-dark .token.punctuation[data-v-7d2bb426]{color:#ccc}.theme-mode-dark .token.attr-name[data-v-7d2bb426],.theme-mode-dark .token.deleted[data-v-7d2bb426],.theme-mode-dark .token.namespace[data-v-7d2bb426],.theme-mode-dark .token.tag[data-v-7d2bb426]{color:#e2777a}.theme-mode-dark .token.function-name[data-v-7d2bb426]{color:#6196cc}.theme-mode-dark .token.boolean[data-v-7d2bb426],.theme-mode-dark .token.function[data-v-7d2bb426],.theme-mode-dark .token.number[data-v-7d2bb426]{color:#f08d49}.theme-mode-dark .token.class-name[data-v-7d2bb426],.theme-mode-dark .token.constant[data-v-7d2bb426],.theme-mode-dark .token.property[data-v-7d2bb426],.theme-mode-dark .token.symbol[data-v-7d2bb426]{color:#f8c555}.theme-mode-dark .token.atrule[data-v-7d2bb426],.theme-mode-dark .token.builtin[data-v-7d2bb426],.theme-mode-dark .token.important[data-v-7d2bb426],.theme-mode-dark .token.keyword[data-v-7d2bb426],.theme-mode-dark .token.selector[data-v-7d2bb426]{color:#cc99cd}.theme-mode-dark .token.attr-value[data-v-7d2bb426],.theme-mode-dark .token.char[data-v-7d2bb426],.theme-mode-dark .token.regex[data-v-7d2bb426],.theme-mode-dark .token.string[data-v-7d2bb426],.theme-mode-dark .token.variable[data-v-7d2bb426]{color:#7ec699}.theme-mode-dark .token.entity[data-v-7d2bb426],.theme-mode-dark .token.operator[data-v-7d2bb426],.theme-mode-dark .token.url[data-v-7d2bb426]{color:#67cdcc}.theme-mode-dark .language-css .token.string[data-v-7d2bb426],.theme-mode-dark .style .token.string[data-v-7d2bb426],.theme-mode-dark .token.entity[data-v-7d2bb426],.theme-mode-dark .token.operator[data-v-7d2bb426],.theme-mode-dark .token.url[data-v-7d2bb426]{background:none}.theme-mode-dark .token.bold[data-v-7d2bb426],.theme-mode-dark .token.important[data-v-7d2bb426]{font-weight:700}.theme-mode-dark .token.italic[data-v-7d2bb426]{font-style:italic}.theme-mode-dark .token.entity[data-v-7d2bb426]{cursor:help}.theme-mode-dark .token.inserted[data-v-7d2bb426]{color:green}.theme-mode-read[data-v-7d2bb426]{--bodyBg:#f5f5d5;--mainBg:#f5f5d5;--sidebarBg:rgba(245,245,213,0.8);--blurBg:rgba(245,245,213,0.9);--textColor:#004050;--textLightenColor:#0085ad;--borderColor:rgba(0,0,0,0.15);--codeBg:#282c34;--codeColor:#fff}.theme-mode-read code[class*=language-][data-v-7d2bb426],.theme-mode-read pre[class*=language-][data-v-7d2bb426]{color:#ccc;background:none;text-shadow:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-read pre[class*=language-][data-v-7d2bb426]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-read :not(pre)>code[class*=language-][data-v-7d2bb426],.theme-mode-read pre[class*=language-][data-v-7d2bb426]{background:#2d2d2d}.theme-mode-read :not(pre)>code[class*=language-][data-v-7d2bb426]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-read .token.block-comment[data-v-7d2bb426],.theme-mode-read .token.cdata[data-v-7d2bb426],.theme-mode-read .token.comment[data-v-7d2bb426],.theme-mode-read .token.doctype[data-v-7d2bb426],.theme-mode-read .token.prolog[data-v-7d2bb426]{color:#999}.theme-mode-read .token.punctuation[data-v-7d2bb426]{color:#ccc}.theme-mode-read .token.attr-name[data-v-7d2bb426],.theme-mode-read .token.deleted[data-v-7d2bb426],.theme-mode-read .token.namespace[data-v-7d2bb426],.theme-mode-read .token.tag[data-v-7d2bb426]{color:#e2777a}.theme-mode-read .token.function-name[data-v-7d2bb426]{color:#6196cc}.theme-mode-read .token.boolean[data-v-7d2bb426],.theme-mode-read .token.function[data-v-7d2bb426],.theme-mode-read .token.number[data-v-7d2bb426]{color:#f08d49}.theme-mode-read .token.class-name[data-v-7d2bb426],.theme-mode-read .token.constant[data-v-7d2bb426],.theme-mode-read .token.property[data-v-7d2bb426],.theme-mode-read .token.symbol[data-v-7d2bb426]{color:#f8c555}.theme-mode-read .token.atrule[data-v-7d2bb426],.theme-mode-read .token.builtin[data-v-7d2bb426],.theme-mode-read .token.important[data-v-7d2bb426],.theme-mode-read .token.keyword[data-v-7d2bb426],.theme-mode-read .token.selector[data-v-7d2bb426]{color:#cc99cd}.theme-mode-read .token.attr-value[data-v-7d2bb426],.theme-mode-read .token.char[data-v-7d2bb426],.theme-mode-read .token.regex[data-v-7d2bb426],.theme-mode-read .token.string[data-v-7d2bb426],.theme-mode-read .token.variable[data-v-7d2bb426]{color:#7ec699}.theme-mode-read .token.entity[data-v-7d2bb426],.theme-mode-read .token.operator[data-v-7d2bb426],.theme-mode-read .token.url[data-v-7d2bb426]{color:#67cdcc}.theme-mode-read .language-css .token.string[data-v-7d2bb426],.theme-mode-read .style .token.string[data-v-7d2bb426],.theme-mode-read .token.entity[data-v-7d2bb426],.theme-mode-read .token.operator[data-v-7d2bb426],.theme-mode-read .token.url[data-v-7d2bb426]{background:none}.theme-mode-read .token.bold[data-v-7d2bb426],.theme-mode-read .token.important[data-v-7d2bb426]{font-weight:700}.theme-mode-read .token.italic[data-v-7d2bb426]{font-style:italic}.theme-mode-read .token.entity[data-v-7d2bb426]{cursor:help}.theme-mode-read .token.inserted[data-v-7d2bb426]{color:green}.home-wrapper .banner[data-v-7d2bb426]{width:100%;min-height:450px;margin-top:3.6rem;color:#fff;position:relative;overflow:hidden}.home-wrapper .banner .banner-conent[data-v-7d2bb426]{max-width:1100px;margin:0 auto;position:relative;z-index:1;overflow:hidden}.home-wrapper .banner .banner-conent .hero[data-v-7d2bb426]{text-align:center;margin-top:3rem}.home-wrapper .banner .banner-conent .hero img[data-v-7d2bb426]{max-width:100%;max-height:240px;display:block;margin:2rem auto 1.5rem}.home-wrapper .banner .banner-conent .hero h1[data-v-7d2bb426]{margin:0;font-size:3.2rem}.home-wrapper .banner .banner-conent .hero .action[data-v-7d2bb426],.home-wrapper .banner .banner-conent .hero .description[data-v-7d2bb426]{margin:1.5rem auto}.home-wrapper .banner .banner-conent .hero .description[data-v-7d2bb426]{max-width:40rem;font-size:1.1rem;line-height:1.3;opacity:.9}.home-wrapper .banner .banner-conent .hero .action-button[data-v-7d2bb426]{display:inline-block;font-size:1.2rem;background-color:#11a8cd;padding:.8rem 1.6rem;border-radius:4px;transition:background-color .1s ease;box-sizing:border-box;border-bottom:1px solid #0f97b9;color:#fff}.home-wrapper .banner .banner-conent .hero .action-button[data-v-7d2bb426]:hover{background-color:#13bee8}.home-wrapper .banner .banner-conent .features[data-v-7d2bb426]{padding:2rem 0;margin-top:2.5rem;display:flex;flex-wrap:wrap;align-items:flex-start;align-content:stretch;justify-content:space-between}.home-wrapper .banner .banner-conent .feature[data-v-7d2bb426]{flex-grow:1;flex-basis:30%;max-width:30%;text-align:center}.home-wrapper .banner .banner-conent .feature a[data-v-7d2bb426]{color:inherit}.home-wrapper .banner .banner-conent .feature a .feature-img[data-v-7d2bb426]{width:10rem;height:10rem;animation:heart-7d2bb426 1.2s ease-in-out 0s infinite alternate;animation-play-state:paused}.home-wrapper .banner .banner-conent .feature a h2[data-v-7d2bb426]{font-weight:500;font-size:1.3rem;border-bottom:none;padding-bottom:0}.home-wrapper .banner .banner-conent .feature a p[data-v-7d2bb426]{opacity:.8;padding:0 .8rem}.home-wrapper .banner .banner-conent .feature:hover .feature-img[data-v-7d2bb426]{animation-play-state:running}.home-wrapper .banner .banner-conent .feature:hover h2[data-v-7d2bb426],.home-wrapper .banner .banner-conent .feature:hover p[data-v-7d2bb426]{color:#11a8cd}.home-wrapper .banner .slide-banner[data-v-7d2bb426]{margin-top:2rem}.home-wrapper .banner .slide-banner .banner-wrapper[data-v-7d2bb426]{position:relative}.home-wrapper .banner .slide-banner .slide-banner-scroll[data-v-7d2bb426]{min-height:1px;overflow:hidden}.home-wrapper .banner .slide-banner .slide-banner-wrapper[data-v-7d2bb426]{height:300px}.home-wrapper .banner .slide-banner .slide-banner-wrapper .slide-item[data-v-7d2bb426]{display:inline-block;height:300px;width:100%;text-align:center}.home-wrapper .banner .slide-banner .slide-banner-wrapper .slide-item a[data-v-7d2bb426]{color:inherit}.home-wrapper .banner .slide-banner .slide-banner-wrapper .slide-item a .feature-img[data-v-7d2bb426]{width:10rem;height:10rem}.home-wrapper .banner .slide-banner .slide-banner-wrapper .slide-item a h2[data-v-7d2bb426]{font-size:1.1rem;font-weight:500;border-bottom:none;padding-bottom:0}.home-wrapper .banner .slide-banner .slide-banner-wrapper .slide-item a p[data-v-7d2bb426]{opacity:.8;padding:0 .8rem}.home-wrapper .banner .slide-banner .docs-wrapper[data-v-7d2bb426]{position:absolute;bottom:25px;left:50%;transform:translateX(-50%)}.home-wrapper .banner .slide-banner .docs-wrapper .doc[data-v-7d2bb426]{display:inline-block;margin:0 4px;width:8px;height:8px;border-radius:50%;background:var(--textColor);opacity:.9}.home-wrapper .banner .slide-banner .docs-wrapper .doc.active[data-v-7d2bb426]{opacity:.5}.home-wrapper .banner.hide-banner[data-v-7d2bb426]{display:none}.home-wrapper .banner.hide-banner+.main-wrapper[data-v-7d2bb426]{margin-top:4.5rem}.home-wrapper .main-wrapper[data-v-7d2bb426]{margin-top:2rem}.home-wrapper .main-wrapper .main-left .card-box[data-v-7d2bb426]{margin-bottom:2rem}.home-wrapper .main-wrapper .main-left .pagination[data-v-7d2bb426]{margin-bottom:3rem}.home-wrapper .main-wrapper .main-left .theme-vdoing-content[data-v-7d2bb426]{padding:0 2rem;overflow:hidden;border:none}.home-wrapper .main-wrapper .main-left .theme-vdoing-content[data-v-7d2bb426]>:first-child{padding-top:2rem}.home-wrapper .main-wrapper .main-left .theme-vdoing-content[data-v-7d2bb426]>:last-child{padding-bottom:2rem}.home-wrapper .main-wrapper .main-right .custom-html-box[data-v-7d2bb426]{padding:0;overflow:hidden}@media (max-width:1025px){.home-wrapper .banner .banner-conent .hero h1[data-v-7d2bb426]{font-size:2.5rem}.home-wrapper .banner .banner-conent .hero .description[data-v-7d2bb426]{font-size:1rem}.home-wrapper .banner .banner-conent .feature a h2[data-v-7d2bb426]{font-size:1.1rem}.home-wrapper .banner .banner-conent .feature a .feature-img[data-v-7d2bb426]{width:9rem;height:9rem}}@media (max-width:719px){.home-wrapper .banner .banner-conent .features[data-v-7d2bb426]{display:none!important}}@media (max-width:419px){.home-wrapper .banner-conent[data-v-7d2bb426]{padding-left:1.5rem;padding-right:1.5rem}.home-wrapper .banner-conent .hero img[data-v-7d2bb426]{max-height:210px;margin:2rem auto 1.2rem}.home-wrapper .banner-conent .hero h1[data-v-7d2bb426]{font-size:2rem}.home-wrapper .banner-conent .hero .action[data-v-7d2bb426],.home-wrapper .banner-conent .hero .description[data-v-7d2bb426],.home-wrapper .banner-conent .hero h1[data-v-7d2bb426]{margin:1.2rem auto}.home-wrapper .banner-conent .hero .description[data-v-7d2bb426]{font-size:1.2rem}.home-wrapper .banner-conent .hero .action-button[data-v-7d2bb426]{font-size:1rem;padding:.6rem 1.2rem}.home-wrapper .banner-conent .feature h2[data-v-7d2bb426]{font-size:1.25rem}}@media (max-width:719px){.theme-style-line .main-wrapper[data-v-7d2bb426]{margin-top:-1px}}@keyframes heart-7d2bb426{0%{transform:translate(0)}to{transform:translateY(8px)}}.search-box{display:inline-block;position:relative;margin-right:1rem}.search-box input{cursor:text;width:10rem;height:2rem;color:#4e6e8e;display:inline-block;border:1px solid #cfd4db;border-radius:2rem;font-size:.9rem;line-height:2rem;padding:0 .5rem 0 2rem;outline:none;transition:all .2s ease;background:#fff url(/db-tutorial/assets/img/search.237d6f6a.svg) .6rem .5rem no-repeat;background-size:1rem}.search-box input:focus{cursor:auto;border-color:#11a8cd}.search-box .suggestions{background:#fff;min-width:500px;max-width:700px;position:absolute;top:2rem;border:1px solid #cfd4db;border-radius:6px;padding:.4rem;list-style-type:none}.search-box .suggestions.align-right{right:0}.search-box .suggestion{line-height:1.4;border-radius:4px;cursor:pointer;width:100%}.search-box .suggestion a{display:block;white-space:normal;color:#415b75;width:100%}.search-box .suggestion a .parent-page-title{color:#fff;font-weight:600;background-color:#11a8cd;padding:5px}.search-box .suggestion a .suggestion-row{border-collapse:collapse;width:100%;display:table}.search-box .suggestion a .suggestion-row .page-title{width:35%;background:#f5f5f5;border:1px solid #eaecef;border-left:none;display:table-cell;text-align:right;padding:5px;font-weight:600}.search-box .suggestion a .suggestion-row .suggestion-content{font-weight:400;border:1px solid #eaecef;border-right:none;width:65%;display:table-cell;padding:5px}.search-box .suggestion a .suggestion-row .suggestion-content .highlight{text-decoration:underline}.search-box .suggestion a .suggestion-row .suggestion-content .header{font-weight:600}.search-box .suggestion.focused{background-color:#f3f4f5}@media (max-width:959px){.search-box input{cursor:pointer;width:0;border-color:transparent;position:relative}.search-box input:focus{cursor:text;left:0;width:10rem}}@media (-ms-high-contrast:none){.search-box input{height:2rem}}@media (max-width:959px) and (min-width:719px){.search-box .suggestions{left:0}}@media (max-width:719px){.search-box{margin-right:0}.search-box input{left:1rem}.search-box .suggestions{right:0}}@media (max-width:419px){.search-box .suggestions{width:calc(100vw - 4rem)}.search-box input:focus{width:8rem}}.sidebar-button{cursor:pointer;display:none;width:1.25rem;height:1.25rem;position:absolute;padding:.6rem;top:.6rem;left:1rem}@media (max-width:719px){.sidebar-button{display:block}}.sidebar-button .icon{display:block;width:1.25rem;height:1.25rem}@media (min-width:720px){.sidebar-button{width:40px;height:40px;display:inline-block;position:fixed;left:0;top:4.6rem;text-align:center;line-height:44px;margin:5px 8px;color:#888;border-radius:50%;padding:0;transition:all .2s}.sidebar-button:hover{background:#11a8cd;color:#fff;box-shadow:0 0 6px #11a8cd}.sidebar-button .icon{display:inline;width:1rem;height:1rem}}.dropdown-enter,.dropdown-leave-to{height:0!important}.dropdown-wrapper{cursor:pointer}.dropdown-wrapper .dropdown-title{display:block;font-size:.9rem;font-family:inherit;cursor:inherit;padding:inherit;line-height:1.4rem;background:transparent;border:none;font-weight:500;color:var(--textColor)}.dropdown-wrapper .dropdown-title:hover{border-color:transparent}.dropdown-wrapper .dropdown-title .arrow{vertical-align:middle;margin-top:-1px;margin-left:.4rem}.dropdown-wrapper .nav-dropdown .dropdown-item{color:inherit;line-height:1.7rem}.dropdown-wrapper .nav-dropdown .dropdown-item h4{margin:.45rem 0 0;border-top:1px solid var(--borderColor);padding:.45rem 1.5rem 0 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper{padding:0;list-style:none}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper .dropdown-subitem{font-size:.9em}.dropdown-wrapper .nav-dropdown .dropdown-item a{display:block;line-height:1.7rem;position:relative;border-bottom:none;font-weight:400;margin-bottom:0;padding:0 1.5rem 0 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active,.dropdown-wrapper .nav-dropdown .dropdown-item a:hover{color:#11a8cd}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active:after{content:"";width:0;height:0;border-left:5px solid #11a8cd;border-top:3px solid transparent;border-bottom:3px solid transparent;position:absolute;top:calc(50% - 2px);left:9px}.dropdown-wrapper .nav-dropdown .dropdown-item:first-child h4{margin-top:0;padding-top:0;border-top:0}@media (max-width:719px){.dropdown-wrapper.open .dropdown-title{margin-bottom:.5rem}.dropdown-wrapper .dropdown-title{font-weight:600;font-size:inherit}.dropdown-wrapper .dropdown-title:hover{color:#11a8cd}.dropdown-wrapper .dropdown-title .link-title{display:none}.dropdown-wrapper .dropdown-title .title{display:inline-block!important}.dropdown-wrapper .nav-dropdown{transition:height .1s ease-out;overflow:hidden}.dropdown-wrapper .nav-dropdown .dropdown-item h4{border-top:0;margin-top:0;padding-top:0}.dropdown-wrapper .nav-dropdown .dropdown-item>a,.dropdown-wrapper .nav-dropdown .dropdown-item h4{font-size:15px;line-height:2rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem{font-size:14px;padding-left:1rem}}@media (min-width:719px){.dropdown-wrapper{height:1.8rem}.dropdown-wrapper.open .nav-dropdown,.dropdown-wrapper:hover .nav-dropdown{display:block!important}.dropdown-wrapper.open:blur{display:none}.dropdown-wrapper .dropdown-title .arrow{border-left:4px solid transparent;border-right:4px solid transparent;border-top:6px solid #ccc;border-bottom:0}.dropdown-wrapper .nav-dropdown{display:none;height:auto!important;box-sizing:border-box;max-height:calc(100vh - 2.7rem);overflow-y:auto;position:absolute;top:100%;right:0;background-color:var(--mainBg);padding:.6rem 0;border-bottom-color:var(--borderColor);border:1px solid var(--borderColor);text-align:left;border-radius:.25rem;white-space:nowrap;margin:0}.nav-item .dropdown-title a.router-link-active,.nav-item .dropdown-title a:hover{margin-bottom:-2px;border-bottom:2px solid #13b9e2}}.nav-links{display:inline-block}.nav-links a{line-height:1.4rem;color:inherit}.nav-links a.router-link-active,.nav-links a:hover{color:#11a8cd}.nav-links .nav-item{position:relative;display:inline-block;margin-left:1.5rem;line-height:2rem}.nav-links .nav-item:first-child{margin-left:0}.nav-links .repo-link{margin-left:1.5rem}@media (max-width:959px){.nav-links .nav-item{margin-left:1.2rem}}@media (max-width:719px){.nav-links .nav-item,.nav-links .repo-link{margin-left:0}}@media (min-width:719px){.nav-links a.router-link-active,.nav-links a:hover{color:var(--textColor)}.nav-item>a:not(.external).router-link-active,.nav-item>a:not(.external):hover{margin-bottom:-2px;border-bottom:2px solid #13b9e2}}.navbar{padding:.7rem 1.5rem;line-height:2.2rem;transition:transform .3s}.navbar a,.navbar img,.navbar span{display:inline-block}.navbar .logo{height:2.2rem;min-width:2.2rem;margin-right:.8rem;vertical-align:top}.navbar .site-name{font-size:1.3rem;font-weight:600;color:var(--textColor);position:relative}.navbar .links{padding-left:1.5rem;box-sizing:border-box;white-space:nowrap;font-size:.9rem;position:absolute;right:1.5rem;top:.7rem;display:flex}.navbar .links .search-box{flex:0 0 auto;vertical-align:top}.hide-navbar .navbar{transform:translateY(-100%)}@media (max-width:959px){.navbar .site-name{display:none}}@media (max-width:719px){.navbar{padding-left:4rem}.navbar .can-hide{display:none}.navbar .links{padding-left:1.5rem}.navbar .site-name{width:calc(100vw - 9.4rem);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}}.page-edit{max-width:860px;padding-top:1rem;padding-bottom:1rem;overflow:auto}.page-edit .edit-link{display:inline-block;float:left;margin:0 2rem .5rem 0}.page-edit .edit-link a{margin-right:.25rem}.page-edit .tags{float:left}.page-edit .tags a{margin:0 .8rem .5rem 0;display:inline-block;color:var(--textLightenColor);padding:.2rem .7rem;font-size:.9em;background-color:hsla(0,0%,50.2%,.08);border-radius:3px;opacity:.8}.page-edit .last-updated{float:right;font-size:.9em}.page-edit .last-updated .prefix{font-weight:500;color:var(--textColor);opacity:.8}.page-edit .last-updated .time{font-weight:400;color:#aaa}@media (max-width:719px){.page-edit .edit-link,.page-edit .tags{margin-bottom:.5rem}.page-edit .last-updated{width:100%;font-size:.8em;text-align:left}}.page-nav{max-width:860px;padding-top:1rem;padding-bottom:0}.page-nav .inner{min-height:2rem;margin-top:0;border-top:1px solid var(--borderColor);padding-top:1rem;overflow:auto}.page-nav .next{float:right}.page-nav-centre-wrap .page-nav-centre{position:fixed;top:50%;width:80px;height:70px;margin-top:-35px;outline:0;transition:all .2s;border-radius:3px;opacity:.55;z-index:99}@media (max-width:1340px){.page-nav-centre-wrap .page-nav-centre{width:50px}}@media (max-width:960px){.page-nav-centre-wrap .page-nav-centre{display:none}}.page-nav-centre-wrap .page-nav-centre:hover{background:hsla(0,0%,60%,.15);opacity:1}.page-nav-centre-wrap .page-nav-centre:hover .tooltip{display:block}.page-nav-centre-wrap .page-nav-centre:before{content:"";display:block;width:10px;height:10px;border-top:2px solid #999;border-right:2px solid #999;position:absolute;top:0;right:0;bottom:0;left:0;margin:auto}.page-nav-centre-wrap .page-nav-centre .tooltip{display:none;background:rgba(0,0,0,.5);color:#fff;padding:4px 8px;font-size:13px;border-radius:3px;position:fixed;max-width:200px;z-index:99}.page-nav-centre-wrap .page-nav-centre-prev{left:0}.page-nav-centre-wrap .page-nav-centre-prev:before{transform:rotate(-135deg)}.page-nav-centre-wrap .page-nav-centre-next{right:0}.page-nav-centre-wrap .page-nav-centre-next:before{transform:rotate(45deg)}.sidebar-open .page-nav-centre-wrap .page-nav-centre-prev{left:18rem}.no-sidebar .page-nav-centre-wrap .page-nav-centre-prev{left:0}.theme-mode-light[data-v-06225672]{--bodyBg:#f4f4f4;--customBlockBg:#f1f1f1;--textColor:#00323c;--borderColor:rgba(0,0,0,0.12)}.theme-mode-dark[data-v-06225672]{--bodyBg:#27272b;--customBlockBg:#27272b;--textColor:#9b9baa;--borderColor:#30363d}.theme-mode-read[data-v-06225672]{--bodyBg:#ececcc;--customBlockBg:#ececcc;--textColor:#704214;--textLightenColor:#963}.theme-style-line.theme-mode-light[data-v-06225672]{--bodyBg:#fff}.theme-style-line.theme-mode-dark[data-v-06225672]{--bodyBg:#1e1e22}.theme-style-line.theme-mode-read[data-v-06225672]{--bodyBg:#f5f5d5}.theme-mode-light[data-v-06225672]{--bodyBg:#fff;--mainBg:#fff;--sidebarBg:hsla(0,0%,100%,0.8);--blurBg:hsla(0,0%,100%,0.9);--textColor:#004050;--textLightenColor:#0085ad;--borderColor:rgba(0,0,0,0.15);--codeBg:#f6f6f6;--codeColor:#525252}.theme-mode-light code[class*=language-][data-v-06225672],.theme-mode-light pre[class*=language-][data-v-06225672]{color:#000;background:none;text-shadow:0 1px #fff;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-light code[class*=language-][data-v-06225672]::-moz-selection,.theme-mode-light code[class*=language-][data-v-06225672] ::-moz-selection,.theme-mode-light pre[class*=language-][data-v-06225672]::-moz-selection,.theme-mode-light pre[class*=language-][data-v-06225672] ::-moz-selection{text-shadow:none;background:#b3d4fc}.theme-mode-light code[class*=language-][data-v-06225672]::selection,.theme-mode-light code[class*=language-][data-v-06225672] ::selection,.theme-mode-light pre[class*=language-][data-v-06225672]::selection,.theme-mode-light pre[class*=language-][data-v-06225672] ::selection{text-shadow:none;background:#b3d4fc}@media print{.theme-mode-light code[class*=language-][data-v-06225672],.theme-mode-light pre[class*=language-][data-v-06225672]{text-shadow:none}}.theme-mode-light pre[class*=language-][data-v-06225672]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-light :not(pre)>code[class*=language-][data-v-06225672],.theme-mode-light pre[class*=language-][data-v-06225672]{background:#f5f2f0}.theme-mode-light :not(pre)>code[class*=language-][data-v-06225672]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-light .token.cdata[data-v-06225672],.theme-mode-light .token.comment[data-v-06225672],.theme-mode-light .token.doctype[data-v-06225672],.theme-mode-light .token.prolog[data-v-06225672]{color:#708090}.theme-mode-light .token.punctuation[data-v-06225672]{color:#999}.theme-mode-light .namespace[data-v-06225672]{opacity:.7}.theme-mode-light .token.boolean[data-v-06225672],.theme-mode-light .token.constant[data-v-06225672],.theme-mode-light .token.deleted[data-v-06225672],.theme-mode-light .token.number[data-v-06225672],.theme-mode-light .token.property[data-v-06225672],.theme-mode-light .token.symbol[data-v-06225672],.theme-mode-light .token.tag[data-v-06225672]{color:#905}.theme-mode-light .token.attr-name[data-v-06225672],.theme-mode-light .token.builtin[data-v-06225672],.theme-mode-light .token.char[data-v-06225672],.theme-mode-light .token.inserted[data-v-06225672],.theme-mode-light .token.selector[data-v-06225672],.theme-mode-light .token.string[data-v-06225672]{color:#690}.theme-mode-light .language-css .token.string[data-v-06225672],.theme-mode-light .style .token.string[data-v-06225672],.theme-mode-light .token.entity[data-v-06225672],.theme-mode-light .token.operator[data-v-06225672],.theme-mode-light .token.url[data-v-06225672]{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.theme-mode-light .token.atrule[data-v-06225672],.theme-mode-light .token.attr-value[data-v-06225672],.theme-mode-light .token.keyword[data-v-06225672]{color:#07a}.theme-mode-light .token.class-name[data-v-06225672],.theme-mode-light .token.function[data-v-06225672]{color:#dd4a68}.theme-mode-light .token.important[data-v-06225672],.theme-mode-light .token.regex[data-v-06225672],.theme-mode-light .token.variable[data-v-06225672]{color:#e90}.theme-mode-light .token.bold[data-v-06225672],.theme-mode-light .token.important[data-v-06225672]{font-weight:700}.theme-mode-light .token.italic[data-v-06225672]{font-style:italic}.theme-mode-light .token.entity[data-v-06225672]{cursor:help}.theme-mode-light div[class*=language-] .highlight-lines .highlighted[data-v-06225672],.theme-mode-light div[class*=language-].line-numbers-mode .highlight-lines .highlighted[data-v-06225672]:before{background-color:hsla(0,0%,78.4%,.4)}.theme-mode-dark[data-v-06225672]{--bodyBg:#1e1e22;--mainBg:#1e1e22;--sidebarBg:rgba(30,30,34,0.8);--blurBg:rgba(30,30,34,0.8);--textColor:#8c8c96;--textLightenColor:#0085ad;--borderColor:#2c2c3a;--codeBg:#252526;--codeColor:#fff}.theme-mode-dark code[class*=language-][data-v-06225672],.theme-mode-dark pre[class*=language-][data-v-06225672]{color:#ccc;background:none;text-shadow:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-dark pre[class*=language-][data-v-06225672]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-dark :not(pre)>code[class*=language-][data-v-06225672],.theme-mode-dark pre[class*=language-][data-v-06225672]{background:#2d2d2d}.theme-mode-dark :not(pre)>code[class*=language-][data-v-06225672]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-dark .token.block-comment[data-v-06225672],.theme-mode-dark .token.cdata[data-v-06225672],.theme-mode-dark .token.comment[data-v-06225672],.theme-mode-dark .token.doctype[data-v-06225672],.theme-mode-dark .token.prolog[data-v-06225672]{color:#999}.theme-mode-dark .token.punctuation[data-v-06225672]{color:#ccc}.theme-mode-dark .token.attr-name[data-v-06225672],.theme-mode-dark .token.deleted[data-v-06225672],.theme-mode-dark .token.namespace[data-v-06225672],.theme-mode-dark .token.tag[data-v-06225672]{color:#e2777a}.theme-mode-dark .token.function-name[data-v-06225672]{color:#6196cc}.theme-mode-dark .token.boolean[data-v-06225672],.theme-mode-dark .token.function[data-v-06225672],.theme-mode-dark .token.number[data-v-06225672]{color:#f08d49}.theme-mode-dark .token.class-name[data-v-06225672],.theme-mode-dark .token.constant[data-v-06225672],.theme-mode-dark .token.property[data-v-06225672],.theme-mode-dark .token.symbol[data-v-06225672]{color:#f8c555}.theme-mode-dark .token.atrule[data-v-06225672],.theme-mode-dark .token.builtin[data-v-06225672],.theme-mode-dark .token.important[data-v-06225672],.theme-mode-dark .token.keyword[data-v-06225672],.theme-mode-dark .token.selector[data-v-06225672]{color:#cc99cd}.theme-mode-dark .token.attr-value[data-v-06225672],.theme-mode-dark .token.char[data-v-06225672],.theme-mode-dark .token.regex[data-v-06225672],.theme-mode-dark .token.string[data-v-06225672],.theme-mode-dark .token.variable[data-v-06225672]{color:#7ec699}.theme-mode-dark .token.entity[data-v-06225672],.theme-mode-dark .token.operator[data-v-06225672],.theme-mode-dark .token.url[data-v-06225672]{color:#67cdcc}.theme-mode-dark .language-css .token.string[data-v-06225672],.theme-mode-dark .style .token.string[data-v-06225672],.theme-mode-dark .token.entity[data-v-06225672],.theme-mode-dark .token.operator[data-v-06225672],.theme-mode-dark .token.url[data-v-06225672]{background:none}.theme-mode-dark .token.bold[data-v-06225672],.theme-mode-dark .token.important[data-v-06225672]{font-weight:700}.theme-mode-dark .token.italic[data-v-06225672]{font-style:italic}.theme-mode-dark .token.entity[data-v-06225672]{cursor:help}.theme-mode-dark .token.inserted[data-v-06225672]{color:green}.theme-mode-read[data-v-06225672]{--bodyBg:#f5f5d5;--mainBg:#f5f5d5;--sidebarBg:rgba(245,245,213,0.8);--blurBg:rgba(245,245,213,0.9);--textColor:#004050;--textLightenColor:#0085ad;--borderColor:rgba(0,0,0,0.15);--codeBg:#282c34;--codeColor:#fff}.theme-mode-read code[class*=language-][data-v-06225672],.theme-mode-read pre[class*=language-][data-v-06225672]{color:#ccc;background:none;text-shadow:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-read pre[class*=language-][data-v-06225672]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-read :not(pre)>code[class*=language-][data-v-06225672],.theme-mode-read pre[class*=language-][data-v-06225672]{background:#2d2d2d}.theme-mode-read :not(pre)>code[class*=language-][data-v-06225672]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-read .token.block-comment[data-v-06225672],.theme-mode-read .token.cdata[data-v-06225672],.theme-mode-read .token.comment[data-v-06225672],.theme-mode-read .token.doctype[data-v-06225672],.theme-mode-read .token.prolog[data-v-06225672]{color:#999}.theme-mode-read .token.punctuation[data-v-06225672]{color:#ccc}.theme-mode-read .token.attr-name[data-v-06225672],.theme-mode-read .token.deleted[data-v-06225672],.theme-mode-read .token.namespace[data-v-06225672],.theme-mode-read .token.tag[data-v-06225672]{color:#e2777a}.theme-mode-read .token.function-name[data-v-06225672]{color:#6196cc}.theme-mode-read .token.boolean[data-v-06225672],.theme-mode-read .token.function[data-v-06225672],.theme-mode-read .token.number[data-v-06225672]{color:#f08d49}.theme-mode-read .token.class-name[data-v-06225672],.theme-mode-read .token.constant[data-v-06225672],.theme-mode-read .token.property[data-v-06225672],.theme-mode-read .token.symbol[data-v-06225672]{color:#f8c555}.theme-mode-read .token.atrule[data-v-06225672],.theme-mode-read .token.builtin[data-v-06225672],.theme-mode-read .token.important[data-v-06225672],.theme-mode-read .token.keyword[data-v-06225672],.theme-mode-read .token.selector[data-v-06225672]{color:#cc99cd}.theme-mode-read .token.attr-value[data-v-06225672],.theme-mode-read .token.char[data-v-06225672],.theme-mode-read .token.regex[data-v-06225672],.theme-mode-read .token.string[data-v-06225672],.theme-mode-read .token.variable[data-v-06225672]{color:#7ec699}.theme-mode-read .token.entity[data-v-06225672],.theme-mode-read .token.operator[data-v-06225672],.theme-mode-read .token.url[data-v-06225672]{color:#67cdcc}.theme-mode-read .language-css .token.string[data-v-06225672],.theme-mode-read .style .token.string[data-v-06225672],.theme-mode-read .token.entity[data-v-06225672],.theme-mode-read .token.operator[data-v-06225672],.theme-mode-read .token.url[data-v-06225672]{background:none}.theme-mode-read .token.bold[data-v-06225672],.theme-mode-read .token.important[data-v-06225672]{font-weight:700}.theme-mode-read .token.italic[data-v-06225672]{font-style:italic}.theme-mode-read .token.entity[data-v-06225672]{cursor:help}.theme-mode-read .token.inserted[data-v-06225672]{color:green}.articleInfo-wrap[data-v-06225672]{max-width:860px}.theme-style-line .articleInfo-wrap .articleInfo[data-v-06225672]{padding-top:.5rem}.articleInfo-wrap[data-v-06225672]{position:relative;z-index:1;color:#888}.articleInfo-wrap .articleInfo[data-v-06225672]{overflow:hidden;font-size:.92rem}.articleInfo-wrap .articleInfo .breadcrumbs[data-v-06225672]{margin:0;padding:0;overflow:hidden;display:inline-block;line-height:2rem}@media (max-width:960px){.articleInfo-wrap .articleInfo .breadcrumbs[data-v-06225672]{width:100%}}.articleInfo-wrap .articleInfo .breadcrumbs li[data-v-06225672]{list-style-type:none;float:left;padding-right:5px}.articleInfo-wrap .articleInfo .breadcrumbs li[data-v-06225672]:after{content:"/";margin-left:5px;color:#999}.articleInfo-wrap .articleInfo .breadcrumbs li[data-v-06225672]:last-child:after{content:""}.articleInfo-wrap .articleInfo .breadcrumbs li a[data-v-06225672]{color:#888}.articleInfo-wrap .articleInfo .breadcrumbs li a[data-v-06225672]:before{font-size:.92rem}.articleInfo-wrap .articleInfo .breadcrumbs li a[data-v-06225672]:hover{color:#11a8cd}.articleInfo-wrap .articleInfo .breadcrumbs li .icon-home[data-v-06225672]{text-decoration:none}.articleInfo-wrap .articleInfo .info[data-v-06225672]{float:right;line-height:32px}@media (max-width:960px){.articleInfo-wrap .articleInfo .info[data-v-06225672]{float:left}}.articleInfo-wrap .articleInfo .info div[data-v-06225672]{float:left;margin-left:20px;font-size:.8rem}@media (max-width:960px){.articleInfo-wrap .articleInfo .info div[data-v-06225672]{margin:0 20px 0 0}}.articleInfo-wrap .articleInfo .info div[data-v-06225672]:before{margin-right:3px}.articleInfo-wrap .articleInfo .info div a[data-v-06225672]{color:#888}.articleInfo-wrap .articleInfo .info div a[data-v-06225672]:hover{text-decoration:none}.articleInfo-wrap .articleInfo .info div a.beLink[data-v-06225672]:hover{color:#11a8cd;text-decoration:underline}.theme-mode-light[data-v-2cf874fa]{--bodyBg:#f4f4f4;--customBlockBg:#f1f1f1;--textColor:#00323c;--borderColor:rgba(0,0,0,0.12)}.theme-mode-dark[data-v-2cf874fa]{--bodyBg:#27272b;--customBlockBg:#27272b;--textColor:#9b9baa;--borderColor:#30363d}.theme-mode-read[data-v-2cf874fa]{--bodyBg:#ececcc;--customBlockBg:#ececcc;--textColor:#704214;--textLightenColor:#963}.theme-style-line.theme-mode-light[data-v-2cf874fa]{--bodyBg:#fff}.theme-style-line.theme-mode-dark[data-v-2cf874fa]{--bodyBg:#1e1e22}.theme-style-line.theme-mode-read[data-v-2cf874fa]{--bodyBg:#f5f5d5}.theme-mode-light[data-v-2cf874fa]{--bodyBg:#fff;--mainBg:#fff;--sidebarBg:hsla(0,0%,100%,0.8);--blurBg:hsla(0,0%,100%,0.9);--textColor:#004050;--textLightenColor:#0085ad;--borderColor:rgba(0,0,0,0.15);--codeBg:#f6f6f6;--codeColor:#525252}.theme-mode-light code[class*=language-][data-v-2cf874fa],.theme-mode-light pre[class*=language-][data-v-2cf874fa]{color:#000;background:none;text-shadow:0 1px #fff;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-light code[class*=language-][data-v-2cf874fa]::-moz-selection,.theme-mode-light code[class*=language-][data-v-2cf874fa] ::-moz-selection,.theme-mode-light pre[class*=language-][data-v-2cf874fa]::-moz-selection,.theme-mode-light pre[class*=language-][data-v-2cf874fa] ::-moz-selection{text-shadow:none;background:#b3d4fc}.theme-mode-light code[class*=language-][data-v-2cf874fa]::selection,.theme-mode-light code[class*=language-][data-v-2cf874fa] ::selection,.theme-mode-light pre[class*=language-][data-v-2cf874fa]::selection,.theme-mode-light pre[class*=language-][data-v-2cf874fa] ::selection{text-shadow:none;background:#b3d4fc}@media print{.theme-mode-light code[class*=language-][data-v-2cf874fa],.theme-mode-light pre[class*=language-][data-v-2cf874fa]{text-shadow:none}}.theme-mode-light pre[class*=language-][data-v-2cf874fa]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-light :not(pre)>code[class*=language-][data-v-2cf874fa],.theme-mode-light pre[class*=language-][data-v-2cf874fa]{background:#f5f2f0}.theme-mode-light :not(pre)>code[class*=language-][data-v-2cf874fa]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-light .token.cdata[data-v-2cf874fa],.theme-mode-light .token.comment[data-v-2cf874fa],.theme-mode-light .token.doctype[data-v-2cf874fa],.theme-mode-light .token.prolog[data-v-2cf874fa]{color:#708090}.theme-mode-light .token.punctuation[data-v-2cf874fa]{color:#999}.theme-mode-light .namespace[data-v-2cf874fa]{opacity:.7}.theme-mode-light .token.boolean[data-v-2cf874fa],.theme-mode-light .token.constant[data-v-2cf874fa],.theme-mode-light .token.deleted[data-v-2cf874fa],.theme-mode-light .token.number[data-v-2cf874fa],.theme-mode-light .token.property[data-v-2cf874fa],.theme-mode-light .token.symbol[data-v-2cf874fa],.theme-mode-light .token.tag[data-v-2cf874fa]{color:#905}.theme-mode-light .token.attr-name[data-v-2cf874fa],.theme-mode-light .token.builtin[data-v-2cf874fa],.theme-mode-light .token.char[data-v-2cf874fa],.theme-mode-light .token.inserted[data-v-2cf874fa],.theme-mode-light .token.selector[data-v-2cf874fa],.theme-mode-light .token.string[data-v-2cf874fa]{color:#690}.theme-mode-light .language-css .token.string[data-v-2cf874fa],.theme-mode-light .style .token.string[data-v-2cf874fa],.theme-mode-light .token.entity[data-v-2cf874fa],.theme-mode-light .token.operator[data-v-2cf874fa],.theme-mode-light .token.url[data-v-2cf874fa]{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.theme-mode-light .token.atrule[data-v-2cf874fa],.theme-mode-light .token.attr-value[data-v-2cf874fa],.theme-mode-light .token.keyword[data-v-2cf874fa]{color:#07a}.theme-mode-light .token.class-name[data-v-2cf874fa],.theme-mode-light .token.function[data-v-2cf874fa]{color:#dd4a68}.theme-mode-light .token.important[data-v-2cf874fa],.theme-mode-light .token.regex[data-v-2cf874fa],.theme-mode-light .token.variable[data-v-2cf874fa]{color:#e90}.theme-mode-light .token.bold[data-v-2cf874fa],.theme-mode-light .token.important[data-v-2cf874fa]{font-weight:700}.theme-mode-light .token.italic[data-v-2cf874fa]{font-style:italic}.theme-mode-light .token.entity[data-v-2cf874fa]{cursor:help}.theme-mode-light div[class*=language-] .highlight-lines .highlighted[data-v-2cf874fa],.theme-mode-light div[class*=language-].line-numbers-mode .highlight-lines .highlighted[data-v-2cf874fa]:before{background-color:hsla(0,0%,78.4%,.4)}.theme-mode-dark[data-v-2cf874fa]{--bodyBg:#1e1e22;--mainBg:#1e1e22;--sidebarBg:rgba(30,30,34,0.8);--blurBg:rgba(30,30,34,0.8);--textColor:#8c8c96;--textLightenColor:#0085ad;--borderColor:#2c2c3a;--codeBg:#252526;--codeColor:#fff}.theme-mode-dark code[class*=language-][data-v-2cf874fa],.theme-mode-dark pre[class*=language-][data-v-2cf874fa]{color:#ccc;background:none;text-shadow:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-dark pre[class*=language-][data-v-2cf874fa]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-dark :not(pre)>code[class*=language-][data-v-2cf874fa],.theme-mode-dark pre[class*=language-][data-v-2cf874fa]{background:#2d2d2d}.theme-mode-dark :not(pre)>code[class*=language-][data-v-2cf874fa]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-dark .token.block-comment[data-v-2cf874fa],.theme-mode-dark .token.cdata[data-v-2cf874fa],.theme-mode-dark .token.comment[data-v-2cf874fa],.theme-mode-dark .token.doctype[data-v-2cf874fa],.theme-mode-dark .token.prolog[data-v-2cf874fa]{color:#999}.theme-mode-dark .token.punctuation[data-v-2cf874fa]{color:#ccc}.theme-mode-dark .token.attr-name[data-v-2cf874fa],.theme-mode-dark .token.deleted[data-v-2cf874fa],.theme-mode-dark .token.namespace[data-v-2cf874fa],.theme-mode-dark .token.tag[data-v-2cf874fa]{color:#e2777a}.theme-mode-dark .token.function-name[data-v-2cf874fa]{color:#6196cc}.theme-mode-dark .token.boolean[data-v-2cf874fa],.theme-mode-dark .token.function[data-v-2cf874fa],.theme-mode-dark .token.number[data-v-2cf874fa]{color:#f08d49}.theme-mode-dark .token.class-name[data-v-2cf874fa],.theme-mode-dark .token.constant[data-v-2cf874fa],.theme-mode-dark .token.property[data-v-2cf874fa],.theme-mode-dark .token.symbol[data-v-2cf874fa]{color:#f8c555}.theme-mode-dark .token.atrule[data-v-2cf874fa],.theme-mode-dark .token.builtin[data-v-2cf874fa],.theme-mode-dark .token.important[data-v-2cf874fa],.theme-mode-dark .token.keyword[data-v-2cf874fa],.theme-mode-dark .token.selector[data-v-2cf874fa]{color:#cc99cd}.theme-mode-dark .token.attr-value[data-v-2cf874fa],.theme-mode-dark .token.char[data-v-2cf874fa],.theme-mode-dark .token.regex[data-v-2cf874fa],.theme-mode-dark .token.string[data-v-2cf874fa],.theme-mode-dark .token.variable[data-v-2cf874fa]{color:#7ec699}.theme-mode-dark .token.entity[data-v-2cf874fa],.theme-mode-dark .token.operator[data-v-2cf874fa],.theme-mode-dark .token.url[data-v-2cf874fa]{color:#67cdcc}.theme-mode-dark .language-css .token.string[data-v-2cf874fa],.theme-mode-dark .style .token.string[data-v-2cf874fa],.theme-mode-dark .token.entity[data-v-2cf874fa],.theme-mode-dark .token.operator[data-v-2cf874fa],.theme-mode-dark .token.url[data-v-2cf874fa]{background:none}.theme-mode-dark .token.bold[data-v-2cf874fa],.theme-mode-dark .token.important[data-v-2cf874fa]{font-weight:700}.theme-mode-dark .token.italic[data-v-2cf874fa]{font-style:italic}.theme-mode-dark .token.entity[data-v-2cf874fa]{cursor:help}.theme-mode-dark .token.inserted[data-v-2cf874fa]{color:green}.theme-mode-read[data-v-2cf874fa]{--bodyBg:#f5f5d5;--mainBg:#f5f5d5;--sidebarBg:rgba(245,245,213,0.8);--blurBg:rgba(245,245,213,0.9);--textColor:#004050;--textLightenColor:#0085ad;--borderColor:rgba(0,0,0,0.15);--codeBg:#282c34;--codeColor:#fff}.theme-mode-read code[class*=language-][data-v-2cf874fa],.theme-mode-read pre[class*=language-][data-v-2cf874fa]{color:#ccc;background:none;text-shadow:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-read pre[class*=language-][data-v-2cf874fa]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-read :not(pre)>code[class*=language-][data-v-2cf874fa],.theme-mode-read pre[class*=language-][data-v-2cf874fa]{background:#2d2d2d}.theme-mode-read :not(pre)>code[class*=language-][data-v-2cf874fa]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-read .token.block-comment[data-v-2cf874fa],.theme-mode-read .token.cdata[data-v-2cf874fa],.theme-mode-read .token.comment[data-v-2cf874fa],.theme-mode-read .token.doctype[data-v-2cf874fa],.theme-mode-read .token.prolog[data-v-2cf874fa]{color:#999}.theme-mode-read .token.punctuation[data-v-2cf874fa]{color:#ccc}.theme-mode-read .token.attr-name[data-v-2cf874fa],.theme-mode-read .token.deleted[data-v-2cf874fa],.theme-mode-read .token.namespace[data-v-2cf874fa],.theme-mode-read .token.tag[data-v-2cf874fa]{color:#e2777a}.theme-mode-read .token.function-name[data-v-2cf874fa]{color:#6196cc}.theme-mode-read .token.boolean[data-v-2cf874fa],.theme-mode-read .token.function[data-v-2cf874fa],.theme-mode-read .token.number[data-v-2cf874fa]{color:#f08d49}.theme-mode-read .token.class-name[data-v-2cf874fa],.theme-mode-read .token.constant[data-v-2cf874fa],.theme-mode-read .token.property[data-v-2cf874fa],.theme-mode-read .token.symbol[data-v-2cf874fa]{color:#f8c555}.theme-mode-read .token.atrule[data-v-2cf874fa],.theme-mode-read .token.builtin[data-v-2cf874fa],.theme-mode-read .token.important[data-v-2cf874fa],.theme-mode-read .token.keyword[data-v-2cf874fa],.theme-mode-read .token.selector[data-v-2cf874fa]{color:#cc99cd}.theme-mode-read .token.attr-value[data-v-2cf874fa],.theme-mode-read .token.char[data-v-2cf874fa],.theme-mode-read .token.regex[data-v-2cf874fa],.theme-mode-read .token.string[data-v-2cf874fa],.theme-mode-read .token.variable[data-v-2cf874fa]{color:#7ec699}.theme-mode-read .token.entity[data-v-2cf874fa],.theme-mode-read .token.operator[data-v-2cf874fa],.theme-mode-read .token.url[data-v-2cf874fa]{color:#67cdcc}.theme-mode-read .language-css .token.string[data-v-2cf874fa],.theme-mode-read .style .token.string[data-v-2cf874fa],.theme-mode-read .token.entity[data-v-2cf874fa],.theme-mode-read .token.operator[data-v-2cf874fa],.theme-mode-read .token.url[data-v-2cf874fa]{background:none}.theme-mode-read .token.bold[data-v-2cf874fa],.theme-mode-read .token.important[data-v-2cf874fa]{font-weight:700}.theme-mode-read .token.italic[data-v-2cf874fa]{font-style:italic}.theme-mode-read .token.entity[data-v-2cf874fa]{cursor:help}.theme-mode-read .token.inserted[data-v-2cf874fa]{color:green}.theme-vdoing-content[data-v-2cf874fa]{margin-bottom:3.6rem}.title-tag[data-v-2cf874fa]{border:1px solid #ff5722;color:#ff5722;font-size:.8rem;padding:0 .35rem;border-radius:.2rem;margin-left:0;transform:translateY(-.05rem);display:inline-block}dd[data-v-2cf874fa],dl[data-v-2cf874fa]{margin:0}.column-wrapper[data-v-2cf874fa]{margin-top:1rem;display:flex;padding-bottom:2rem;border-bottom:1px solid var(--borderColor)}.column-wrapper img[data-v-2cf874fa]{width:80px;height:80px;border-radius:2px;margin-right:1rem}.column-wrapper .column-info .title[data-v-2cf874fa]{font-size:1.6rem}.column-wrapper .column-info .description[data-v-2cf874fa]{color:var(--textColor);opacity:.8;margin:.5rem 0}.catalogue-wrapper .catalogue-title[data-v-2cf874fa]{font-size:1.45rem;margin:2rem 0}.catalogue-wrapper .catalogue-content dl[data-v-2cf874fa]{margin-bottom:1.8rem}.catalogue-wrapper .catalogue-content dl.inline[data-v-2cf874fa]{display:inline-block;width:50%;margin-bottom:1rem}@media (max-width:419px){.catalogue-wrapper .catalogue-content dl.inline[data-v-2cf874fa]{width:100%}}.catalogue-wrapper .catalogue-content dl.inline a[data-v-2cf874fa]{width:100%}.catalogue-wrapper .catalogue-content dl:not(.inline) dt[data-v-2cf874fa]{margin-top:-3.6rem;padding-top:3.6rem}.catalogue-wrapper .catalogue-content dl dt[data-v-2cf874fa]{font-size:1.1rem}.catalogue-wrapper .catalogue-content dl dt:hover .header-anchor[data-v-2cf874fa]{opacity:1}.catalogue-wrapper .catalogue-content dl dd[data-v-2cf874fa]{margin-top:.7rem;margin-left:1rem}.catalogue-wrapper .catalogue-content dl dd a[data-v-2cf874fa]:not(.header-anchor){margin-bottom:.5rem;display:inline-block;width:50%}.catalogue-wrapper .catalogue-content dl dd a[data-v-2cf874fa]:not(.header-anchor):hover{color:#ff5722;text-decoration:none}@media (max-width:720px){.catalogue-wrapper .catalogue-content dl dd a[data-v-2cf874fa]:not(.header-anchor){width:100%}}.catalogue-wrapper .catalogue-content dl .sub-cat-wrap[data-v-2cf874fa]{margin:5px 0 8px;font-size:.95rem}.catalogue-wrapper .catalogue-content dl .sub-cat-wrap>a[data-v-2cf874fa]{padding-left:1rem;box-sizing:border-box}.catalogue-wrapper .catalogue-content dl .sub-cat-wrap .sub-title[data-v-2cf874fa]{margin-top:-3.6rem;padding-top:3.6rem;margin-bottom:6px;font-size:1rem}.catalogue-wrapper .catalogue-content dl .sub-cat-wrap:hover .header-anchor[data-v-2cf874fa]{opacity:1}.theme-style-line .right-menu-wrapper .right-menu-margin{border-left:1px solid var(--borderColor)}.right-menu-wrapper{width:230px;float:right;margin-right:-285px;position:sticky;top:0;font-size:.8rem}.right-menu-wrapper .right-menu-margin{margin-top:4.6rem;border-radius:3px;overflow:hidden}.right-menu-wrapper .right-menu-title{padding:10px 15px 0;background:var(--mainBg);font-size:1rem}.right-menu-wrapper .right-menu-title:after{content:"";display:block;width:100%;height:1px;background:var(--borderColor);margin-top:10px}.right-menu-wrapper .right-menu-content{max-height:80vh;position:relative;overflow:hidden;background:var(--mainBg);padding:4px 3px 4px 0}.right-menu-wrapper .right-menu-content::-webkit-scrollbar{width:3px;height:3px}.right-menu-wrapper .right-menu-content::-webkit-scrollbar-track-piece{background:none}.right-menu-wrapper .right-menu-content::-webkit-scrollbar-thumb:vertical{background-color:hsla(0,0%,49%,.3)}.right-menu-wrapper .right-menu-content:hover{overflow-y:auto;padding-right:0}.right-menu-wrapper .right-menu-content .right-menu-item{padding:4px 15px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;position:relative}.right-menu-wrapper .right-menu-content .right-menu-item.level2{font-size:.8rem}.right-menu-wrapper .right-menu-content .right-menu-item.level3{padding-left:27px}.right-menu-wrapper .right-menu-content .right-menu-item.level4{padding-left:37px}.right-menu-wrapper .right-menu-content .right-menu-item.level5{padding-left:47px}.right-menu-wrapper .right-menu-content .right-menu-item.level6{padding-left:57px}.right-menu-wrapper .right-menu-content .right-menu-item.active:before{content:"";position:absolute;top:5px;left:0;width:3px;height:14px;background:#11a8cd;border-radius:0 4px 4px 0}.right-menu-wrapper .right-menu-content .right-menu-item.active a{color:#11a8cd;opacity:1}.right-menu-wrapper .right-menu-content .right-menu-item a{color:var(--textColor);opacity:.75;display:inline-block;width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.right-menu-wrapper .right-menu-content .right-menu-item a:hover{opacity:1}.right-menu-wrapper .right-menu-content:hover{color:#11a8cd}.page>*{max-width:860px;margin:0 auto;padding:1rem 2.5rem 2rem}.page>:not(.footer){background:var(--mainBg);box-shadow:0 1px 2px 0 rgba(0,0,0,.1);margin-bottom:1rem}@media (min-width:940px){.page>:not(.footer){border-radius:2px}}@media (max-width:959px){.page>*{padding:1rem 2rem}}@media (max-width:419px){.page>*{padding:1rem 1.5rem}}.page{padding-bottom:2rem;display:block}@media (max-width:719px){.page{padding-top:3.6rem}}@media (min-width:719px){.page{padding-top:5.1rem}}@media (min-width:719px){.theme-style-line .page{padding-top:3.6rem}}.theme-style-line .page>:not(.footer){box-shadow:0 0}@media (min-width:720px){.theme-style-line .page .placeholder{height:1.2rem}}.theme-vdoing-wrapper .content-wrapper{position:relative}.theme-vdoing-wrapper h1 .title-tag{height:1.5rem;line-height:1.5rem;border:1px solid #ff5722;color:#ff5722;font-size:1rem;padding:0 .4rem;border-radius:.2rem;margin-left:.5rem;transform:translateY(-.25rem);display:inline-block}.theme-vdoing-wrapper h1 img{margin-bottom:-.2rem;margin-right:.2rem;max-width:2.2rem;max-height:2.2rem}.theme-vdoing-wrapper{--linesColor:rgba(50,0,0,0.05)}.theme-vdoing-wrapper.bg-style-1{background-image:linear-gradient(90deg,var(--linesColor) 3%,transparent 0),linear-gradient(0deg,var(--linesColor) 3%,transparent 0);background-position:50%;background-size:20px 20px}.theme-vdoing-wrapper.bg-style-2{background-image:repeating-linear-gradient(0,var(--linesColor),var(--linesColor) 1px,transparent 0,transparent 50%);background-size:30px 30px}.theme-vdoing-wrapper.bg-style-3{background-image:repeating-linear-gradient(90deg,var(--linesColor),var(--linesColor) 1px,transparent 0,transparent 50%);background-size:30px 30px}.theme-vdoing-wrapper.bg-style-4{background-image:repeating-linear-gradient(-45deg,var(--linesColor),var(--linesColor) 1px,transparent 0,transparent 50%);background-size:20px 20px}.theme-vdoing-wrapper.bg-style-5{background-image:repeating-linear-gradient(45deg,var(--linesColor),var(--linesColor) 1px,transparent 0,transparent 50%);background-size:20px 20px}.theme-vdoing-wrapper.bg-style-6{background-image:radial-gradient(var(--linesColor) 1px,transparent 0);background-size:10px 10px}.theme-mode-dark .theme-vdoing-wrapper{--linesColor:hsla(0,0%,49%,0.05)}@media (min-width:720px) and (max-width:1279px){.have-rightmenu .page{padding-right:.8rem!important}}@media (max-width:1279px){.have-rightmenu .right-menu-wrapper{display:none}}@media (min-width:1280px){.have-rightmenu .sidebar .sidebar-sub-headers{display:none}}.theme-container.only-sidebarItem:not(.have-rightmenu) .sidebar,.theme-container.only-sidebarItem:not(.have-rightmenu) .sidebar-button{display:none}@media (min-width:720px){.theme-container.only-sidebarItem:not(.have-rightmenu) .page{padding-left:.8rem!important}}@media (max-width:719px){.theme-container.only-sidebarItem:not(.have-rightmenu) .page{padding-left:0!important}.theme-container.only-sidebarItem:not(.have-rightmenu) .sidebar,.theme-container.only-sidebarItem:not(.have-rightmenu) .sidebar-button{display:block}}@media (min-width:720px) and (max-width:1279px){.theme-container.only-sidebarItem.have-rightmenu .sidebar,.theme-container.only-sidebarItem.have-rightmenu .sidebar-button{display:block}}@media (min-width:1280px){.theme-container.only-sidebarItem.have-rightmenu .sidebar,.theme-container.only-sidebarItem.have-rightmenu .sidebar-button{display:none}}.categories-page .categories-wrapper{position:sticky;top:4.5rem;max-height:calc(100vh - 10rem);min-height:4.2rem}@media (max-width:719px){.categories-page .categories-wrapper{display:none}}.categories-page .categories-wrapper .categories{padding-right:.5rem;max-height:calc(100vh - 14rem);min-height:2.2rem;overflow-y:auto;transition:all .2s;position:relative}.categories-page .categories-wrapper .categories::-webkit-scrollbar-track-piece{background-color:rgba(0,0,0,.05)}.categories-page .categories-wrapper .categories::-webkit-scrollbar-thumb:vertical{background-color:rgba(0,0,0,.15)}.categories-page .categories-wrapper .categories:hover::-webkit-scrollbar-track-piece{background-color:rgba(0,0,0,.1)}.categories-page .categories-wrapper .categories:hover::-webkit-scrollbar-thumb:vertical{background-color:rgba(0,0,0,.25)}.categories-page .main-left .categories-wrapper{position:relative;top:0;padding:.9rem 1.5rem;margin-bottom:.9rem;max-height:15rem;border-radius:0;display:none}@media (max-width:719px){.categories-page .main-left .categories-wrapper{display:block}}.categories-page .main-left .categories-wrapper .categories{max-height:12.3rem}@media (max-width:719px){.theme-style-line .categories-page .main-left .categories-wrapper{margin-top:-.91rem;margin-bottom:-1px;padding:.9rem .2rem .5rem}}.tags-page .tags-wrapper{position:sticky;top:4.5rem;max-height:calc(100vh - 10rem);min-height:4.2rem}@media (max-width:719px){.tags-page .tags-wrapper{display:none}}.tags-page .tags-wrapper .tags{max-height:calc(100vh - 14rem);min-height:2.2rem;overflow-x:hidden;overflow-y:auto;transition:all .2s}.tags-page .tags-wrapper .tags::-webkit-scrollbar-track-piece{background-color:rgba(0,0,0,.05)}.tags-page .tags-wrapper .tags::-webkit-scrollbar-thumb:vertical{background-color:rgba(0,0,0,.15)}.tags-page .tags-wrapper .tags:hover::-webkit-scrollbar-track-piece{background-color:rgba(0,0,0,.1)}.tags-page .tags-wrapper .tags:hover::-webkit-scrollbar-thumb:vertical{background-color:rgba(0,0,0,.25)}.tags-page .main-left .tags-wrapper{position:relative;top:0;padding:.9rem 1.5rem;margin-bottom:.9rem;max-height:15rem;border-radius:0;display:none}@media (max-width:719px){.tags-page .main-left .tags-wrapper{display:block}}.tags-page .main-left .tags-wrapper .tags{max-height:11.5rem}@media (max-width:719px){.theme-style-line .tags-page .main-left .tags-wrapper{margin-top:-.91rem;margin-bottom:-1px}}.archives-page .theme-vdoing-wrapper{max-width:860px;margin:0 auto;padding:1rem 2.5rem 2rem}.archives-page .theme-vdoing-wrapper:not(.footer){background:var(--mainBg);box-shadow:0 1px 2px 0 rgba(0,0,0,.1);margin-bottom:1rem}@media (min-width:940px){.archives-page .theme-vdoing-wrapper:not(.footer){border-radius:2px}}@media (max-width:959px){.archives-page .theme-vdoing-wrapper{padding:1rem 2rem}}@media (max-width:419px){.archives-page .theme-vdoing-wrapper{padding:1rem 1.5rem}}.theme-style-line .archives-page .theme-vdoing-wrapper{box-shadow:0 0}.archives-page .theme-vdoing-wrapper{position:relative}@media (min-width:940px){.archives-page .theme-vdoing-wrapper{margin-top:1.5rem!important}}.archives-page .theme-vdoing-wrapper .count{text-align:right;margin-top:-2.5rem;font-size:.85rem;opacity:.8}.archives-page .theme-vdoing-wrapper li,.archives-page .theme-vdoing-wrapper ul{margin:0;padding:0}.archives-page .theme-vdoing-wrapper ul{margin-top:2rem}.archives-page .theme-vdoing-wrapper li{list-style:none}.archives-page .theme-vdoing-wrapper li.year{position:sticky;top:3.6rem;background:var(--mainBg);z-index:1}.archives-page .theme-vdoing-wrapper li.year:not(:first-child){margin-top:3.5rem}.archives-page .theme-vdoing-wrapper li h2{margin-bottom:.8rem;font-weight:400;padding:.5rem 0}.archives-page .theme-vdoing-wrapper li h2 span{font-size:.85rem;font-weight:300;float:right;margin-top:1rem}.archives-page .theme-vdoing-wrapper li a{display:block;color:var(--textColor);transition:padding .3s;padding:.5rem 2rem;line-height:1.2rem}.archives-page .theme-vdoing-wrapper li a:hover{padding-left:2.5rem;color:#11a8cd;background:#f9f9f9}@media (max-width:940px){.archives-page .theme-vdoing-wrapper li a{padding:.5rem 1rem;font-weight:400}.archives-page .theme-vdoing-wrapper li a:hover{padding-left:1.5rem}}.archives-page .theme-vdoing-wrapper li a span.date{opacity:.6;font-size:.85rem;font-weight:400;margin-right:.3rem}.archives-page .theme-vdoing-wrapper li a .title-tag{border:1px solid #ff5722;color:#ff5722;font-size:.8rem;padding:0 .35rem;border-radius:.2rem;margin-left:0;transform:translateY(-.05rem);display:inline-block}.archives-page .theme-vdoing-wrapper .loadmore{text-align:center;margin-top:1rem;opacity:.5}.theme-mode-dark .archives-page .theme-vdoing-wrapper li a:hover,.theme-mode-read .archives-page .theme-vdoing-wrapper li a:hover{background:var(--customBlockBg)}.hide-navbar .archives-page .theme-vdoing-wrapper li.year{top:0}.sidebar-group .sidebar-group{padding-left:.5em}.sidebar-group:not(.collapsable) .sidebar-heading:not(.clickable){cursor:auto;color:inherit}.sidebar-group.is-sub-group{padding-left:0}.sidebar-group.is-sub-group>.sidebar-heading{font-size:1.01em;line-height:1.4;font-weight:700;padding-left:2rem}.sidebar-group.is-sub-group>.sidebar-group-items{padding-left:1rem}.sidebar-group.is-sub-group>.sidebar-group-items>li>.sidebar-link{font-size:.98em;border-left:none}.sidebar-group.depth-2>.sidebar-heading{border-left:none}.sidebar-heading{color:var(--textColor);transition:color .15s ease;cursor:pointer;font-size:1.1em;font-weight:700;padding:.35rem 1.5rem .35rem 1.25rem;width:100%;box-sizing:border-box;margin:0;border-left:.25rem solid transparent}.sidebar-heading.open,.sidebar-heading:hover{color:inherit}.sidebar-heading .arrow{position:relative;top:-.12em;left:.5em}.sidebar-heading.clickable.active{font-weight:600;color:#11a8cd;border-left-color:#11a8cd}.sidebar-heading.clickable:hover{color:#11a8cd}.sidebar-group-items{transition:height .1s ease-out;font-size:.95em;overflow:hidden}.sidebar .sidebar-sub-headers{padding-left:1rem;font-size:.95em}.sidebar .sidebar-sub-headers .level4{padding-left:.2rem}.sidebar .sidebar-sub-headers .level5{padding-left:.4rem}.sidebar .sidebar-sub-headers .level6{padding-left:.6rem}a.sidebar-link{font-size:1em;font-weight:400;display:inline-block;color:var(--textColor);border-left:.25rem solid transparent;padding:.35rem 1rem .35rem 1.25rem;line-height:1.4;width:100%;box-sizing:border-box}a.sidebar-link:hover{color:#11a8cd}a.sidebar-link.active{font-weight:600;color:#11a8cd;border-left-color:#11a8cd}.sidebar-group a.sidebar-link{padding-left:2rem}.sidebar-sub-headers a.sidebar-link{padding-top:.25rem;padding-bottom:.25rem;border-left:none}.sidebar-sub-headers a.sidebar-link.active{font-weight:500}.sidebar ul{padding:0;margin:0;list-style-type:none}.sidebar a{display:inline-block}.sidebar .nav-links{display:none;border-bottom:1px solid var(--borderColor);padding:.5rem 0 .75rem}.sidebar .nav-links a{font-weight:600}.sidebar .nav-links .nav-item,.sidebar .nav-links .repo-link{display:block;line-height:1.25rem;font-size:1.1em;padding:.5rem 0 .5rem 1.5rem}.sidebar>.sidebar-links{padding:1.5rem 0}.sidebar>.sidebar-links>li>a.sidebar-link{font-size:1.1em;line-height:1.7;font-weight:700}.sidebar>.sidebar-links>li:not(:first-child){margin-top:.75rem}.sidebar .blogger{display:none;border-bottom:1px solid var(--borderColor)}.sidebar .blogger img{width:60px;height:60px;border-radius:5px;margin:.75rem 1rem}.sidebar .blogger .blogger-info{flex:1;padding:0 .3rem .3rem 0}.sidebar .blogger .blogger-info h3{margin:.95rem 0 .6rem;font-size:1.1rem}.sidebar .blogger .blogger-info .icons .iconfont{font-size:1.2rem;padding-right:.6rem;color:#777}.sidebar .sidebar-slot{margin-bottom:-.5rem;font-size:.85rem}.sidebar .sidebar-slot.sidebar-slot-top{padding:1.5rem 1.5rem 0}.sidebar .sidebar-slot.sidebar-slot-bottom{padding:0 1.5rem 1.5rem}@media (max-width:719px){.sidebar .blogger{display:flex}.sidebar .nav-links{display:block}.sidebar .nav-links .dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active:after{top:calc(1rem - 2px)}.sidebar>.sidebar-links{padding:1rem 0}}.yellowBorder{border-radius:5px;box-shadow:0 0 15px #ffe089!important}.buttons{position:fixed;right:2rem;bottom:2.5rem;z-index:11}@media (max-width:959px){.buttons{right:1rem;bottom:1.5rem}}.buttons .button{width:2.2rem;height:2.2rem;line-height:2.2rem;border-radius:50%;box-shadow:0 2px 6px rgba(0,0,0,.15);margin-top:.9rem;text-align:center;cursor:pointer;transition:all .5s;background:var(--blurBg)}.buttons .button.hover{background:#11a8cd;box-shadow:0 0 15px #11a8cd}.buttons .button.hover:before{color:#fff}@media (any-hover:hover){.buttons .button:hover{background:#11a8cd;box-shadow:0 0 15px #11a8cd}.buttons .button:hover:before{color:#fff}}.buttons .button .select-box{margin:0;padding:.8rem 0;position:absolute;bottom:0;right:1.5rem;background:var(--mainBg);border:1px solid var(--borderColor);width:120px;border-radius:6px;box-shadow:0 0 15px hsla(0,0%,100%,.2)}.buttons .button .select-box li{list-style:none;line-height:2rem;font-size:.95rem}.buttons .button .select-box li:hover{color:#11a8cd}.buttons .button .select-box li.active{background-color:hsla(0,0%,58.8%,.2);color:#11a8cd}.mode-enter-active,.mode-leave-active{transition:all .3s}.mode-enter,.mode-leave-to{opacity:0;transform:scale(.8)}.fade-enter-active,.fade-leave-active{transition:opacity .2s}.fade-enter,.fade-leave-to{opacity:0}.footer{padding:5rem 1.5rem 2.5rem;text-align:center;color:#666;box-sizing:border-box;font-size:.85rem;transition:all .2s ease}.footer>span{line-height:1.5rem}.footer .icons{margin-bottom:12px}.footer .icons .iconfont{padding:0 10px;font-size:1.3rem}.footer a{color:inherit}.footer a:hover{color:#11a8cd}@media (min-width:720px){.sidebar-open .footer{width:auto;padding-left:19.5rem}}@media (min-width:1520px){.have-rightmenu .footer{padding-right:231.5px}}.no-sidebar .footer{width:auto;padding-left:1.5rem}.body-bg{position:fixed;left:0;top:0;z-index:-999999;height:100vh;width:100vw;transition:background .5s}.theme-mode-light{--bodyBg:#f4f4f4;--customBlockBg:#f1f1f1;--textColor:#00323c;--borderColor:rgba(0,0,0,0.12)}.theme-mode-dark{--bodyBg:#27272b;--customBlockBg:#27272b;--textColor:#9b9baa;--borderColor:#30363d}.theme-mode-read{--bodyBg:#ececcc;--customBlockBg:#ececcc;--textColor:#704214;--textLightenColor:#963}.theme-style-line.theme-mode-light{--bodyBg:#fff}.theme-style-line.theme-mode-dark{--bodyBg:#1e1e22}.theme-style-line.theme-mode-read{--bodyBg:#f5f5d5}.theme-mode-light{--bodyBg:#fff;--mainBg:#fff;--sidebarBg:hsla(0,0%,100%,0.8);--blurBg:hsla(0,0%,100%,0.9);--textColor:#004050;--textLightenColor:#0085ad;--borderColor:rgba(0,0,0,0.15);--codeBg:#f6f6f6;--codeColor:#525252}.theme-mode-light code[class*=language-],.theme-mode-light pre[class*=language-]{color:#000;background:none;text-shadow:0 1px #fff;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-light code[class*=language-]::-moz-selection,.theme-mode-light code[class*=language-] ::-moz-selection,.theme-mode-light pre[class*=language-]::-moz-selection,.theme-mode-light pre[class*=language-] ::-moz-selection{text-shadow:none;background:#b3d4fc}.theme-mode-light code[class*=language-]::selection,.theme-mode-light code[class*=language-] ::selection,.theme-mode-light pre[class*=language-]::selection,.theme-mode-light pre[class*=language-] ::selection{text-shadow:none;background:#b3d4fc}@media print{.theme-mode-light code[class*=language-],.theme-mode-light pre[class*=language-]{text-shadow:none}}.theme-mode-light pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-light :not(pre)>code[class*=language-],.theme-mode-light pre[class*=language-]{background:#f5f2f0}.theme-mode-light :not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-light .token.cdata,.theme-mode-light .token.comment,.theme-mode-light .token.doctype,.theme-mode-light .token.prolog{color:#708090}.theme-mode-light .token.punctuation{color:#999}.theme-mode-light .namespace{opacity:.7}.theme-mode-light .token.boolean,.theme-mode-light .token.constant,.theme-mode-light .token.deleted,.theme-mode-light .token.number,.theme-mode-light .token.property,.theme-mode-light .token.symbol,.theme-mode-light .token.tag{color:#905}.theme-mode-light .token.attr-name,.theme-mode-light .token.builtin,.theme-mode-light .token.char,.theme-mode-light .token.inserted,.theme-mode-light .token.selector,.theme-mode-light .token.string{color:#690}.theme-mode-light .language-css .token.string,.theme-mode-light .style .token.string,.theme-mode-light .token.entity,.theme-mode-light .token.operator,.theme-mode-light .token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.theme-mode-light .token.atrule,.theme-mode-light .token.attr-value,.theme-mode-light .token.keyword{color:#07a}.theme-mode-light .token.class-name,.theme-mode-light .token.function{color:#dd4a68}.theme-mode-light .token.important,.theme-mode-light .token.regex,.theme-mode-light .token.variable{color:#e90}.theme-mode-light .token.bold,.theme-mode-light .token.important{font-weight:700}.theme-mode-light .token.italic{font-style:italic}.theme-mode-light .token.entity{cursor:help}.theme-mode-light div[class*=language-] .highlight-lines .highlighted,.theme-mode-light div[class*=language-].line-numbers-mode .highlight-lines .highlighted:before{background-color:hsla(0,0%,78.4%,.4)}.theme-mode-dark{--bodyBg:#1e1e22;--mainBg:#1e1e22;--sidebarBg:rgba(30,30,34,0.8);--blurBg:rgba(30,30,34,0.8);--textColor:#8c8c96;--textLightenColor:#0085ad;--borderColor:#2c2c3a;--codeBg:#252526;--codeColor:#fff}.theme-mode-dark code[class*=language-],.theme-mode-dark pre[class*=language-]{color:#ccc;background:none;text-shadow:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-dark pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-dark :not(pre)>code[class*=language-],.theme-mode-dark pre[class*=language-]{background:#2d2d2d}.theme-mode-dark :not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-dark .token.block-comment,.theme-mode-dark .token.cdata,.theme-mode-dark .token.comment,.theme-mode-dark .token.doctype,.theme-mode-dark .token.prolog{color:#999}.theme-mode-dark .token.punctuation{color:#ccc}.theme-mode-dark .token.attr-name,.theme-mode-dark .token.deleted,.theme-mode-dark .token.namespace,.theme-mode-dark .token.tag{color:#e2777a}.theme-mode-dark .token.function-name{color:#6196cc}.theme-mode-dark .token.boolean,.theme-mode-dark .token.function,.theme-mode-dark .token.number{color:#f08d49}.theme-mode-dark .token.class-name,.theme-mode-dark .token.constant,.theme-mode-dark .token.property,.theme-mode-dark .token.symbol{color:#f8c555}.theme-mode-dark .token.atrule,.theme-mode-dark .token.builtin,.theme-mode-dark .token.important,.theme-mode-dark .token.keyword,.theme-mode-dark .token.selector{color:#cc99cd}.theme-mode-dark .token.attr-value,.theme-mode-dark .token.char,.theme-mode-dark .token.regex,.theme-mode-dark .token.string,.theme-mode-dark .token.variable{color:#7ec699}.theme-mode-dark .token.entity,.theme-mode-dark .token.operator,.theme-mode-dark .token.url{color:#67cdcc}.theme-mode-dark .language-css .token.string,.theme-mode-dark .style .token.string,.theme-mode-dark .token.entity,.theme-mode-dark .token.operator,.theme-mode-dark .token.url{background:none}.theme-mode-dark .token.bold,.theme-mode-dark .token.important{font-weight:700}.theme-mode-dark .token.italic{font-style:italic}.theme-mode-dark .token.entity{cursor:help}.theme-mode-dark .token.inserted{color:green}.theme-mode-read{--bodyBg:#f5f5d5;--mainBg:#f5f5d5;--sidebarBg:rgba(245,245,213,0.8);--blurBg:rgba(245,245,213,0.9);--textColor:#004050;--textLightenColor:#0085ad;--borderColor:rgba(0,0,0,0.15);--codeBg:#282c34;--codeColor:#fff}.theme-mode-read code[class*=language-],.theme-mode-read pre[class*=language-]{color:#ccc;background:none;text-shadow:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-read pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-read :not(pre)>code[class*=language-],.theme-mode-read pre[class*=language-]{background:#2d2d2d}.theme-mode-read :not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-read .token.block-comment,.theme-mode-read .token.cdata,.theme-mode-read .token.comment,.theme-mode-read .token.doctype,.theme-mode-read .token.prolog{color:#999}.theme-mode-read .token.punctuation{color:#ccc}.theme-mode-read .token.attr-name,.theme-mode-read .token.deleted,.theme-mode-read .token.namespace,.theme-mode-read .token.tag{color:#e2777a}.theme-mode-read .token.function-name{color:#6196cc}.theme-mode-read .token.boolean,.theme-mode-read .token.function,.theme-mode-read .token.number{color:#f08d49}.theme-mode-read .token.class-name,.theme-mode-read .token.constant,.theme-mode-read .token.property,.theme-mode-read .token.symbol{color:#f8c555}.theme-mode-read .token.atrule,.theme-mode-read .token.builtin,.theme-mode-read .token.important,.theme-mode-read .token.keyword,.theme-mode-read .token.selector{color:#cc99cd}.theme-mode-read .token.attr-value,.theme-mode-read .token.char,.theme-mode-read .token.regex,.theme-mode-read .token.string,.theme-mode-read .token.variable{color:#7ec699}.theme-mode-read .token.entity,.theme-mode-read .token.operator,.theme-mode-read .token.url{color:#67cdcc}.theme-mode-read .language-css .token.string,.theme-mode-read .style .token.string,.theme-mode-read .token.entity,.theme-mode-read .token.operator,.theme-mode-read .token.url{background:none}.theme-mode-read .token.bold,.theme-mode-read .token.important{font-weight:700}.theme-mode-read .token.italic{font-style:italic}.theme-mode-read .token.entity{cursor:help}.theme-mode-read .token.inserted{color:green}.custom-html-window{position:fixed;bottom:0;display:flex;overflow:hidden;font-weight:350}@media (max-width:960px){.custom-html-window{display:none}}.custom-html-window .custom-wrapper{position:relative;max-width:200px;max-height:400px}.custom-html-window .custom-wrapper .close-but{cursor:pointer;position:absolute;right:0;top:0;font-size:1.5rem;line-height:1.5rem;width:1.5rem;height:1.5rem;opacity:0;transition:all .2s}.custom-html-window .custom-wrapper .close-but:hover{opacity:.9}.custom-html-window .custom-wrapper:hover .close-but{opacity:.7}.custom-html-window.custom-html-window-lb{left:0;z-index:99}.custom-html-window.custom-html-window-lb>*{align-self:flex-end}.custom-html-window.custom-html-window-rb{right:80px;z-index:10;justify-content:flex-end}.custom-html-window.custom-html-window-rb>*{align-self:flex-end}.theme-mode-light[data-v-d5affa18]{--bodyBg:#f4f4f4;--customBlockBg:#f1f1f1;--textColor:#00323c;--borderColor:rgba(0,0,0,0.12)}.theme-mode-dark[data-v-d5affa18]{--bodyBg:#27272b;--customBlockBg:#27272b;--textColor:#9b9baa;--borderColor:#30363d}.theme-mode-read[data-v-d5affa18]{--bodyBg:#ececcc;--customBlockBg:#ececcc;--textColor:#704214;--textLightenColor:#963}.theme-style-line.theme-mode-light[data-v-d5affa18]{--bodyBg:#fff}.theme-style-line.theme-mode-dark[data-v-d5affa18]{--bodyBg:#1e1e22}.theme-style-line.theme-mode-read[data-v-d5affa18]{--bodyBg:#f5f5d5}.theme-mode-light[data-v-d5affa18]{--bodyBg:#fff;--mainBg:#fff;--sidebarBg:hsla(0,0%,100%,0.8);--blurBg:hsla(0,0%,100%,0.9);--textColor:#004050;--textLightenColor:#0085ad;--borderColor:rgba(0,0,0,0.15);--codeBg:#f6f6f6;--codeColor:#525252}.theme-mode-light code[class*=language-][data-v-d5affa18],.theme-mode-light pre[class*=language-][data-v-d5affa18]{color:#000;background:none;text-shadow:0 1px #fff;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-light code[class*=language-][data-v-d5affa18]::-moz-selection,.theme-mode-light code[class*=language-][data-v-d5affa18] ::-moz-selection,.theme-mode-light pre[class*=language-][data-v-d5affa18]::-moz-selection,.theme-mode-light pre[class*=language-][data-v-d5affa18] ::-moz-selection{text-shadow:none;background:#b3d4fc}.theme-mode-light code[class*=language-][data-v-d5affa18]::selection,.theme-mode-light code[class*=language-][data-v-d5affa18] ::selection,.theme-mode-light pre[class*=language-][data-v-d5affa18]::selection,.theme-mode-light pre[class*=language-][data-v-d5affa18] ::selection{text-shadow:none;background:#b3d4fc}@media print{.theme-mode-light code[class*=language-][data-v-d5affa18],.theme-mode-light pre[class*=language-][data-v-d5affa18]{text-shadow:none}}.theme-mode-light pre[class*=language-][data-v-d5affa18]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-light :not(pre)>code[class*=language-][data-v-d5affa18],.theme-mode-light pre[class*=language-][data-v-d5affa18]{background:#f5f2f0}.theme-mode-light :not(pre)>code[class*=language-][data-v-d5affa18]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-light .token.cdata[data-v-d5affa18],.theme-mode-light .token.comment[data-v-d5affa18],.theme-mode-light .token.doctype[data-v-d5affa18],.theme-mode-light .token.prolog[data-v-d5affa18]{color:#708090}.theme-mode-light .token.punctuation[data-v-d5affa18]{color:#999}.theme-mode-light .namespace[data-v-d5affa18]{opacity:.7}.theme-mode-light .token.boolean[data-v-d5affa18],.theme-mode-light .token.constant[data-v-d5affa18],.theme-mode-light .token.deleted[data-v-d5affa18],.theme-mode-light .token.number[data-v-d5affa18],.theme-mode-light .token.property[data-v-d5affa18],.theme-mode-light .token.symbol[data-v-d5affa18],.theme-mode-light .token.tag[data-v-d5affa18]{color:#905}.theme-mode-light .token.attr-name[data-v-d5affa18],.theme-mode-light .token.builtin[data-v-d5affa18],.theme-mode-light .token.char[data-v-d5affa18],.theme-mode-light .token.inserted[data-v-d5affa18],.theme-mode-light .token.selector[data-v-d5affa18],.theme-mode-light .token.string[data-v-d5affa18]{color:#690}.theme-mode-light .language-css .token.string[data-v-d5affa18],.theme-mode-light .style .token.string[data-v-d5affa18],.theme-mode-light .token.entity[data-v-d5affa18],.theme-mode-light .token.operator[data-v-d5affa18],.theme-mode-light .token.url[data-v-d5affa18]{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.theme-mode-light .token.atrule[data-v-d5affa18],.theme-mode-light .token.attr-value[data-v-d5affa18],.theme-mode-light .token.keyword[data-v-d5affa18]{color:#07a}.theme-mode-light .token.class-name[data-v-d5affa18],.theme-mode-light .token.function[data-v-d5affa18]{color:#dd4a68}.theme-mode-light .token.important[data-v-d5affa18],.theme-mode-light .token.regex[data-v-d5affa18],.theme-mode-light .token.variable[data-v-d5affa18]{color:#e90}.theme-mode-light .token.bold[data-v-d5affa18],.theme-mode-light .token.important[data-v-d5affa18]{font-weight:700}.theme-mode-light .token.italic[data-v-d5affa18]{font-style:italic}.theme-mode-light .token.entity[data-v-d5affa18]{cursor:help}.theme-mode-light div[class*=language-] .highlight-lines .highlighted[data-v-d5affa18],.theme-mode-light div[class*=language-].line-numbers-mode .highlight-lines .highlighted[data-v-d5affa18]:before{background-color:hsla(0,0%,78.4%,.4)}.theme-mode-dark[data-v-d5affa18]{--bodyBg:#1e1e22;--mainBg:#1e1e22;--sidebarBg:rgba(30,30,34,0.8);--blurBg:rgba(30,30,34,0.8);--textColor:#8c8c96;--textLightenColor:#0085ad;--borderColor:#2c2c3a;--codeBg:#252526;--codeColor:#fff}.theme-mode-dark code[class*=language-][data-v-d5affa18],.theme-mode-dark pre[class*=language-][data-v-d5affa18]{color:#ccc;background:none;text-shadow:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-dark pre[class*=language-][data-v-d5affa18]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-dark :not(pre)>code[class*=language-][data-v-d5affa18],.theme-mode-dark pre[class*=language-][data-v-d5affa18]{background:#2d2d2d}.theme-mode-dark :not(pre)>code[class*=language-][data-v-d5affa18]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-dark .token.block-comment[data-v-d5affa18],.theme-mode-dark .token.cdata[data-v-d5affa18],.theme-mode-dark .token.comment[data-v-d5affa18],.theme-mode-dark .token.doctype[data-v-d5affa18],.theme-mode-dark .token.prolog[data-v-d5affa18]{color:#999}.theme-mode-dark .token.punctuation[data-v-d5affa18]{color:#ccc}.theme-mode-dark .token.attr-name[data-v-d5affa18],.theme-mode-dark .token.deleted[data-v-d5affa18],.theme-mode-dark .token.namespace[data-v-d5affa18],.theme-mode-dark .token.tag[data-v-d5affa18]{color:#e2777a}.theme-mode-dark .token.function-name[data-v-d5affa18]{color:#6196cc}.theme-mode-dark .token.boolean[data-v-d5affa18],.theme-mode-dark .token.function[data-v-d5affa18],.theme-mode-dark .token.number[data-v-d5affa18]{color:#f08d49}.theme-mode-dark .token.class-name[data-v-d5affa18],.theme-mode-dark .token.constant[data-v-d5affa18],.theme-mode-dark .token.property[data-v-d5affa18],.theme-mode-dark .token.symbol[data-v-d5affa18]{color:#f8c555}.theme-mode-dark .token.atrule[data-v-d5affa18],.theme-mode-dark .token.builtin[data-v-d5affa18],.theme-mode-dark .token.important[data-v-d5affa18],.theme-mode-dark .token.keyword[data-v-d5affa18],.theme-mode-dark .token.selector[data-v-d5affa18]{color:#cc99cd}.theme-mode-dark .token.attr-value[data-v-d5affa18],.theme-mode-dark .token.char[data-v-d5affa18],.theme-mode-dark .token.regex[data-v-d5affa18],.theme-mode-dark .token.string[data-v-d5affa18],.theme-mode-dark .token.variable[data-v-d5affa18]{color:#7ec699}.theme-mode-dark .token.entity[data-v-d5affa18],.theme-mode-dark .token.operator[data-v-d5affa18],.theme-mode-dark .token.url[data-v-d5affa18]{color:#67cdcc}.theme-mode-dark .language-css .token.string[data-v-d5affa18],.theme-mode-dark .style .token.string[data-v-d5affa18],.theme-mode-dark .token.entity[data-v-d5affa18],.theme-mode-dark .token.operator[data-v-d5affa18],.theme-mode-dark .token.url[data-v-d5affa18]{background:none}.theme-mode-dark .token.bold[data-v-d5affa18],.theme-mode-dark .token.important[data-v-d5affa18]{font-weight:700}.theme-mode-dark .token.italic[data-v-d5affa18]{font-style:italic}.theme-mode-dark .token.entity[data-v-d5affa18]{cursor:help}.theme-mode-dark .token.inserted[data-v-d5affa18]{color:green}.theme-mode-read[data-v-d5affa18]{--bodyBg:#f5f5d5;--mainBg:#f5f5d5;--sidebarBg:rgba(245,245,213,0.8);--blurBg:rgba(245,245,213,0.9);--textColor:#004050;--textLightenColor:#0085ad;--borderColor:rgba(0,0,0,0.15);--codeBg:#282c34;--codeColor:#fff}.theme-mode-read code[class*=language-][data-v-d5affa18],.theme-mode-read pre[class*=language-][data-v-d5affa18]{color:#ccc;background:none;text-shadow:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.theme-mode-read pre[class*=language-][data-v-d5affa18]{padding:1em;margin:.5em 0;overflow:auto}.theme-mode-read :not(pre)>code[class*=language-][data-v-d5affa18],.theme-mode-read pre[class*=language-][data-v-d5affa18]{background:#2d2d2d}.theme-mode-read :not(pre)>code[class*=language-][data-v-d5affa18]{padding:.1em;border-radius:.3em;white-space:normal}.theme-mode-read .token.block-comment[data-v-d5affa18],.theme-mode-read .token.cdata[data-v-d5affa18],.theme-mode-read .token.comment[data-v-d5affa18],.theme-mode-read .token.doctype[data-v-d5affa18],.theme-mode-read .token.prolog[data-v-d5affa18]{color:#999}.theme-mode-read .token.punctuation[data-v-d5affa18]{color:#ccc}.theme-mode-read .token.attr-name[data-v-d5affa18],.theme-mode-read .token.deleted[data-v-d5affa18],.theme-mode-read .token.namespace[data-v-d5affa18],.theme-mode-read .token.tag[data-v-d5affa18]{color:#e2777a}.theme-mode-read .token.function-name[data-v-d5affa18]{color:#6196cc}.theme-mode-read .token.boolean[data-v-d5affa18],.theme-mode-read .token.function[data-v-d5affa18],.theme-mode-read .token.number[data-v-d5affa18]{color:#f08d49}.theme-mode-read .token.class-name[data-v-d5affa18],.theme-mode-read .token.constant[data-v-d5affa18],.theme-mode-read .token.property[data-v-d5affa18],.theme-mode-read .token.symbol[data-v-d5affa18]{color:#f8c555}.theme-mode-read .token.atrule[data-v-d5affa18],.theme-mode-read .token.builtin[data-v-d5affa18],.theme-mode-read .token.important[data-v-d5affa18],.theme-mode-read .token.keyword[data-v-d5affa18],.theme-mode-read .token.selector[data-v-d5affa18]{color:#cc99cd}.theme-mode-read .token.attr-value[data-v-d5affa18],.theme-mode-read .token.char[data-v-d5affa18],.theme-mode-read .token.regex[data-v-d5affa18],.theme-mode-read .token.string[data-v-d5affa18],.theme-mode-read .token.variable[data-v-d5affa18]{color:#7ec699}.theme-mode-read .token.entity[data-v-d5affa18],.theme-mode-read .token.operator[data-v-d5affa18],.theme-mode-read .token.url[data-v-d5affa18]{color:#67cdcc}.theme-mode-read .language-css .token.string[data-v-d5affa18],.theme-mode-read .style .token.string[data-v-d5affa18],.theme-mode-read .token.entity[data-v-d5affa18],.theme-mode-read .token.operator[data-v-d5affa18],.theme-mode-read .token.url[data-v-d5affa18]{background:none}.theme-mode-read .token.bold[data-v-d5affa18],.theme-mode-read .token.important[data-v-d5affa18]{font-weight:700}.theme-mode-read .token.italic[data-v-d5affa18]{font-style:italic}.theme-mode-read .token.entity[data-v-d5affa18]{cursor:help}.theme-mode-read .token.inserted[data-v-d5affa18]{color:green}.badge[data-v-d5affa18]{display:inline-block;font-size:14px;height:18px;line-height:18px;border-radius:3px;padding:0 6px;color:#fff}.badge.green[data-v-d5affa18],.badge.tip[data-v-d5affa18],.badge[data-v-d5affa18]{background-color:#42b983}.badge.error[data-v-d5affa18]{background-color:#da5961}.badge.warn[data-v-d5affa18],.badge.warning[data-v-d5affa18],.badge.yellow[data-v-d5affa18]{background-color:#e7c000}.badge+.badge[data-v-d5affa18]{margin-left:5px}@font-face{font-family:octicons-link;src:url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==) format("woff")}.markdown-body{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;color:#24292e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;font-size:16px;line-height:1.5;word-wrap:break-word}.markdown-body .pl-c{color:#6a737d}.markdown-body .pl-c1,.markdown-body .pl-s .pl-v{color:#005cc5}.markdown-body .pl-e,.markdown-body .pl-en{color:#6f42c1}.markdown-body .pl-s .pl-s1,.markdown-body .pl-smi{color:#24292e}.markdown-body .pl-ent{color:#22863a}.markdown-body .pl-k{color:#d73a49}.markdown-body .pl-pds,.markdown-body .pl-s,.markdown-body .pl-s .pl-pse .pl-s1,.markdown-body .pl-sr,.markdown-body .pl-sr .pl-cce,.markdown-body .pl-sr .pl-sra,.markdown-body .pl-sr .pl-sre{color:#032f62}.markdown-body .pl-smw,.markdown-body .pl-v{color:#e36209}.markdown-body .pl-bu{color:#b31d28}.markdown-body .pl-ii{color:#fafbfc;background-color:#b31d28}.markdown-body .pl-c2{color:#fafbfc;background-color:#d73a49}.markdown-body .pl-c2:before{content:"^M"}.markdown-body .pl-sr .pl-cce{font-weight:700;color:#22863a}.markdown-body .pl-ml{color:#735c0f}.markdown-body .pl-mh,.markdown-body .pl-mh .pl-en,.markdown-body .pl-ms{font-weight:700;color:#005cc5}.markdown-body .pl-mi{font-style:italic;color:#24292e}.markdown-body .pl-mb{font-weight:700;color:#24292e}.markdown-body .pl-md{color:#b31d28;background-color:#ffeef0}.markdown-body .pl-mi1{color:#22863a;background-color:#f0fff4}.markdown-body .pl-mc{color:#e36209;background-color:#ffebda}.markdown-body .pl-mi2{color:#f6f8fa;background-color:#005cc5}.markdown-body .pl-mdr{font-weight:700;color:#6f42c1}.markdown-body .pl-ba{color:#586069}.markdown-body .pl-sg{color:#959da5}.markdown-body .pl-corl{text-decoration:underline;color:#032f62}.markdown-body .octicon{display:inline-block;vertical-align:text-top;fill:currentColor}.markdown-body a{background-color:transparent;-webkit-text-decoration-skip:objects}.markdown-body a:active,.markdown-body a:hover{outline-width:0}.markdown-body strong{font-weight:inherit;font-weight:bolder}.markdown-body h1{margin:.67em 0}.markdown-body img{border-style:none}.markdown-body svg:not(:root){overflow:hidden}.markdown-body code,.markdown-body kbd,.markdown-body pre{font-family:monospace,monospace;font-size:1em}.markdown-body hr{box-sizing:content-box;overflow:visible}.markdown-body input{font:inherit;margin:0;overflow:visible}.markdown-body [type=checkbox]{box-sizing:border-box;padding:0}.markdown-body *{box-sizing:border-box}.markdown-body input{font-family:inherit;font-size:inherit;line-height:inherit}.markdown-body a{color:#0366d6;text-decoration:none}.markdown-body a:hover{text-decoration:underline}.markdown-body strong{font-weight:600}.markdown-body hr{height:0;margin:15px 0;overflow:hidden;background:transparent;border-bottom:1px solid #dfe2e5}.markdown-body hr:after,.markdown-body hr:before{display:table;content:""}.markdown-body hr:after{clear:both}.markdown-body table{border-spacing:0;border-collapse:collapse}.markdown-body td,.markdown-body th{padding:0}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:0;margin-bottom:0}.markdown-body h1{font-size:32px;font-weight:600}.markdown-body h2{font-size:24px;font-weight:600}.markdown-body h3{font-size:20px;font-weight:600}.markdown-body h4{font-size:16px;font-weight:600}.markdown-body h5{font-size:14px;font-weight:600}.markdown-body h6{font-size:12px;font-weight:600}.markdown-body p{margin-top:0;margin-bottom:10px}.markdown-body blockquote{margin:0}.markdown-body ol,.markdown-body ul{padding-left:0;margin-top:0;margin-bottom:0}.markdown-body ol ol,.markdown-body ul ol{list-style-type:lower-roman}.markdown-body ol ol ol,.markdown-body ol ul ol,.markdown-body ul ol ol,.markdown-body ul ul ol{list-style-type:lower-alpha}.markdown-body dd{margin-left:0}.markdown-body code{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;font-size:12px}.markdown-body pre{margin-top:0;margin-bottom:0;font:12px SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace}.markdown-body .octicon{vertical-align:text-bottom}.markdown-body .pl-0{padding-left:0!important}.markdown-body .pl-1{padding-left:4px!important}.markdown-body .pl-2{padding-left:8px!important}.markdown-body .pl-3{padding-left:16px!important}.markdown-body .pl-4{padding-left:24px!important}.markdown-body .pl-5{padding-left:32px!important}.markdown-body .pl-6{padding-left:40px!important}.markdown-body:after,.markdown-body:before{display:table;content:""}.markdown-body:after{clear:both}.markdown-body>:first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body .anchor{float:left;padding-right:4px;margin-left:-20px;line-height:1}.markdown-body .anchor:focus{outline:none}.markdown-body blockquote,.markdown-body dl,.markdown-body ol,.markdown-body p,.markdown-body pre,.markdown-body table,.markdown-body ul{margin-top:0;margin-bottom:16px}.markdown-body hr{height:.25em;padding:0;margin:24px 0;background-color:#e1e4e8;border:0}.markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid #dfe2e5}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body kbd{font-size:11px;border:1px solid #c6cbd1;border-bottom-color:#959da5;box-shadow:inset 0 -1px 0 #959da5}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#1b1f23;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1{font-size:2em}.markdown-body h1,.markdown-body h2{padding-bottom:.3em;border-bottom:1px solid #eaecef}.markdown-body h2{font-size:1.5em}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:.875em}.markdown-body h6{font-size:.85em;color:#6a737d}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:0;margin-bottom:0}.markdown-body li>p{margin-top:16px}.markdown-body li+li{margin-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:600}.markdown-body dl dd{padding:0 16px;margin-bottom:16px}.markdown-body table{display:block;width:100%;overflow:auto}.markdown-body table th{font-weight:600}.markdown-body table td,.markdown-body table th{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.markdown-body img{max-width:100%;box-sizing:content-box;background-color:#fff}.markdown-body code{padding:.2em 0;margin:0;font-size:85%;background-color:rgba(27,31,35,.05);border-radius:3px}.markdown-body code:after,.markdown-body code:before{letter-spacing:-.2em;content:"\A0"}.markdown-body pre{word-wrap:normal}.markdown-body pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:transparent;border:0}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:3px}.markdown-body pre code{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}.markdown-body pre code:after,.markdown-body pre code:before{content:normal}.markdown-body .full-commit .btn-outline:not(:disabled):hover{color:#005cc5;border-color:#005cc5}.markdown-body kbd{display:inline-block;padding:3px 5px;font:11px SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:1px solid #d1d5da;border-bottom-color:#c6cbd1;border-radius:3px;box-shadow:inset 0 -1px 0 #c6cbd1}.markdown-body :checked+.radio-label{position:relative;z-index:1;border-color:#0366d6}.markdown-body .task-list-item{list-style-type:none}.markdown-body .task-list-item+.task-list-item{margin-top:3px}.markdown-body .task-list-item input{margin:0 .2em .25em -1.6em;vertical-align:middle}.markdown-body hr{border-bottom-color:#eee}.gt-container{font-size:16px}.gt-container,.gt-container *{box-sizing:border-box}.gt-container a{color:#6190e8}.gt-container a:hover{color:#81a6ed;border-color:#81a6ed}.gt-container a.is--active{color:#333;cursor:default!important}.gt-container a.is--active:hover{color:#333}.gt-container .hide{display:none!important}.gt-container .gt-svg{display:inline-block;width:1em;height:1em;vertical-align:sub}.gt-container .gt-svg svg{width:100%;height:100%;fill:#6190e8}.gt-container .gt-ico{display:inline-block}.gt-container .gt-ico-text{margin-left:.3125em}.gt-container .gt-ico-github,.gt-container .gt-ico-github .gt-svg{width:100%;height:100%}.gt-container .gt-ico-github svg{fill:inherit}.gt-container .gt-spinner{position:relative}.gt-container .gt-spinner:before{content:"";box-sizing:border-box;position:absolute;top:3px;width:.75em;height:.75em;margin-top:-.1875em;margin-left:-.375em;border-radius:50%;border:1px solid #fff;border-top-color:#6190e8;animation:gt-kf-rotate .6s linear infinite}.gt-container .gt-loader{position:relative;border:1px solid #999;animation:gt-kf-rotate 1.5s ease infinite;display:inline-block;font-style:normal;width:1.75em;height:1.75em;line-height:1.75em;border-radius:50%}.gt-container .gt-loader:before{content:"";position:absolute;display:block;top:0;left:50%;margin-top:-.1875em;margin-left:-.1875em;width:.375em;height:.375em;background-color:#999;border-radius:50%}.gt-container .gt-avatar{display:inline-block;width:3.125em;height:3.125em}@media (max-width:479px){.gt-container .gt-avatar{width:2em;height:2em}}.gt-container .gt-avatar img{width:100%;height:auto;border-radius:3px}.gt-container .gt-avatar-github{width:3em;height:3em;cursor:pointer}@media (max-width:479px){.gt-container .gt-avatar-github{width:1.875em;height:1.875em}}.gt-container .gt-btn{padding:.75em 1.25em;display:inline-block;line-height:1;text-decoration:none;white-space:nowrap;cursor:pointer;border:1px solid #6190e8;border-radius:5px;background-color:#6190e8;color:#fff;outline:none;font-size:.75em}.gt-container .gt-btn-text{font-weight:400}.gt-container .gt-btn-loading{position:relative;margin-left:.5em;display:inline-block;width:.75em;height:1em;vertical-align:top}.gt-container .gt-btn.is--disable{cursor:not-allowed;opacity:.5}.gt-container .gt-btn-login{margin-right:0}.gt-container .gt-btn-preview{background-color:#fff;color:#6190e8}.gt-container .gt-btn-preview:hover{background-color:#f2f2f2;border-color:#81a6ed}.gt-container .gt-btn-public:hover{background-color:#81a6ed;border-color:#81a6ed}.gt-container .gt-error{text-align:center;margin:.625em;color:#ff3860}.gt-container .gt-initing{padding:1.25em 0;text-align:center}.gt-container .gt-initing-text{margin:.625em auto;font-size:92%}.gt-container .gt-no-init{padding:1.25em 0;text-align:center}.gt-container .gt-link{border-bottom:1px dotted #6190e8}.gt-container .gt-link-counts,.gt-container .gt-link-project{text-decoration:none}.gt-container .gt-meta{margin:1.25em 0;padding:1em 0;border-bottom:1px solid #e9e9e9;font-size:1em;position:relative;z-index:10}.gt-container .gt-meta:after,.gt-container .gt-meta:before{content:" ";display:table}.gt-container .gt-meta:after{clear:both}.gt-container .gt-counts{margin:0 .625em 0 0}.gt-container .gt-user{float:right;margin:0;font-size:92%}.gt-container .gt-user-pic{width:16px;height:16px;vertical-align:top;margin-right:.5em}.gt-container .gt-user-inner{display:inline-block;cursor:pointer}.gt-container .gt-user .gt-ico{margin:0 0 0 .3125em}.gt-container .gt-user .gt-ico svg{fill:inherit}.gt-container .gt-user .is--poping .gt-ico svg{fill:#6190e8}.gt-container .gt-version{color:#a1a1a1;margin-left:.375em}.gt-container .gt-copyright{margin:0 .9375em .5em;border-top:1px solid #e9e9e9;padding-top:.5em}.gt-container .gt-popup{position:absolute;right:0;top:2.375em;background:#fff;display:inline-block;border:1px solid #e9e9e9;padding:.625em 0;font-size:.875em;letter-spacing:.5px}.gt-container .gt-popup .gt-action{cursor:pointer;display:block;margin:.5em 0;padding:0 1.125em;position:relative;text-decoration:none}.gt-container .gt-popup .gt-action.is--active:before{content:"";width:.25em;height:.25em;background:#6190e8;position:absolute;left:.5em;top:.4375em}.gt-container .gt-header{position:relative;display:flex}.gt-container .gt-header-comment{flex:1;margin-left:1.25em}@media (max-width:479px){.gt-container .gt-header-comment{margin-left:.875em}}.gt-container .gt-header-textarea{padding:.75em;display:block;box-sizing:border-box;width:100%;min-height:5.125em;max-height:15em;border-radius:5px;border:1px solid rgba(0,0,0,.1);font-size:.875em;word-wrap:break-word;resize:vertical;background-color:#f6f6f6;outline:none;transition:all .25s ease}.gt-container .gt-header-textarea:hover{background-color:#fbfbfb}.gt-container .gt-header-preview{padding:.75em;border-radius:5px;border:1px solid rgba(0,0,0,.1);background-color:#f6f6f6}.gt-container .gt-header-controls{position:relative;margin:.75em 0 0}.gt-container .gt-header-controls:after,.gt-container .gt-header-controls:before{content:" ";display:table}.gt-container .gt-header-controls:after{clear:both}@media (max-width:479px){.gt-container .gt-header-controls{margin:0}}.gt-container .gt-header-controls-tip{font-size:.875em;color:#6190e8;text-decoration:none;vertical-align:sub}@media (max-width:479px){.gt-container .gt-header-controls-tip{display:none}}.gt-container .gt-header-controls .gt-btn{float:right;margin-left:1.25em}@media (max-width:479px){.gt-container .gt-header-controls .gt-btn{float:none;width:100%;margin:.75em 0 0}}.gt-container:after{content:"";position:fixed;bottom:100%;left:0;right:0;top:0;opacity:0}.gt-container.gt-input-focused{position:relative}.gt-container.gt-input-focused:after{content:"";position:fixed;bottom:0;left:0;right:0;top:0;background:#000;opacity:.6;transition:opacity .3s,bottom 0s;z-index:9999}.gt-container.gt-input-focused .gt-header-comment{z-index:10000}.gt-container .gt-comments{padding-top:1.25em}.gt-container .gt-comments-null{text-align:center}.gt-container .gt-comments-controls{margin:1.25em 0;text-align:center}.gt-container .gt-comment{position:relative;padding:.625em 0;display:flex}.gt-container .gt-comment-content{flex:1;margin-left:1.25em;padding:.75em 1em;background-color:#f9f9f9;overflow:auto;transition:all .25s ease}.gt-container .gt-comment-content:hover{box-shadow:0 .625em 3.75em 0 #f4f4f4}@media (max-width:479px){.gt-container .gt-comment-content{margin-left:.875em;padding:.625em .75em}}.gt-container .gt-comment-header{margin-bottom:.5em;font-size:.875em;position:relative}.gt-container .gt-comment-block-1{float:right;height:1.375em;width:2em}.gt-container .gt-comment-block-2{float:right;height:1.375em;width:4em}.gt-container .gt-comment-username{font-weight:500;color:#6190e8;text-decoration:none}.gt-container .gt-comment-username:hover{text-decoration:underline}.gt-container .gt-comment-date,.gt-container .gt-comment-text{margin-left:.5em;color:#a1a1a1}.gt-container .gt-comment-edit,.gt-container .gt-comment-like,.gt-container .gt-comment-reply{position:absolute;height:1.375em}.gt-container .gt-comment-edit:hover,.gt-container .gt-comment-like:hover,.gt-container .gt-comment-reply:hover{cursor:pointer}.gt-container .gt-comment-like{top:0;right:2em}.gt-container .gt-comment-edit,.gt-container .gt-comment-reply{top:0;right:0}.gt-container .gt-comment-body{color:#333!important}.gt-container .gt-comment-body .email-hidden-toggle a{display:inline-block;height:12px;padding:0 9px;font-size:12px;font-weight:600;line-height:6px;color:#444d56;text-decoration:none;vertical-align:middle;background:#dfe2e5;border-radius:1px}.gt-container .gt-comment-body .email-hidden-toggle a:hover{background-color:#c6cbd1}.gt-container .gt-comment-body .email-hidden-reply{display:none;white-space:pre-wrap}.gt-container .gt-comment-body .email-hidden-reply .email-signature-reply{padding:0 15px;margin:15px 0;color:#586069;border-left:4px solid #dfe2e5}.gt-container .gt-comment-body .email-hidden-reply.expanded{display:block}.gt-container .gt-comment-admin .gt-comment-content{background-color:#f6f9fe}@keyframes gt-kf-rotate{0%{transform:rotate(0)}to{transform:rotate(1turn)}}
\ No newline at end of file
diff --git a/assets/img/search.237d6f6a.svg b/assets/img/search.237d6f6a.svg
new file mode 100644
index 00000000..18ed22ab
--- /dev/null
+++ b/assets/img/search.237d6f6a.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/js/10.1ecb1548.js b/assets/js/10.1ecb1548.js
new file mode 100644
index 00000000..8b0b9492
--- /dev/null
+++ b/assets/js/10.1ecb1548.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{347:function(a,t,s){"use strict";s.r(t);var n=s(4),e=Object(n.a)({},(function(){var a=this,t=a._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[t("h1",{attrs:{id:"版本管理中间件-flyway"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#版本管理中间件-flyway"}},[a._v("#")]),a._v(" 版本管理中间件 Flyway")]),a._v(" "),t("blockquote",[t("p",[a._v("Flyway 是一个数据迁移工具。")])]),a._v(" "),t("h2",{attrs:{id:"简介"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#简介"}},[a._v("#")]),a._v(" 简介")]),a._v(" "),t("h3",{attrs:{id:"什么是-flyway"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#什么是-flyway"}},[a._v("#")]),a._v(" 什么是 Flyway")]),a._v(" "),t("p",[t("strong",[a._v("Flyway 是一个开源的数据库迁移工具。")])]),a._v(" "),t("h3",{attrs:{id:"为什么要使用数据迁移"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#为什么要使用数据迁移"}},[a._v("#")]),a._v(" 为什么要使用数据迁移")]),a._v(" "),t("p",[a._v("为了说明数据迁移的作用,我们来举一个示例:")]),a._v(" "),t("p",[a._v("(1)假设,有一个叫做 Shiny 的项目,它的架构是一个叫做 Shiny Soft 的 App 连接叫做 Shiny DB 的数据库。")]),a._v(" "),t("p",[a._v("(2)对于大多数项目而言,最简单的持续集成场景如下所示:")]),a._v(" "),t("p",[t("img",{attrs:{src:"https://flywaydb.org/assets/balsamiq/Environments.png",alt:"img"}})]),a._v(" "),t("p",[a._v("这意味着,我们不仅仅要处理一份环境中的修改,由此会引入一些版本冲突问题:")]),a._v(" "),t("p",[a._v("在代码侧(即应用软件)的版本问题比较容易解决:")]),a._v(" "),t("ul",[t("li",[a._v("有方便的版本控制工具")]),a._v(" "),t("li",[a._v("有可复用的构建和持续集成")]),a._v(" "),t("li",[a._v("规范的发布和部署过程")])]),a._v(" "),t("p",[a._v("那么,数据库层面的版本问题如何解决呢?")]),a._v(" "),t("p",[a._v("目前仍然没有方便的数据库版本工具。许多项目仍使用 sql 脚本来解决版本冲突,甚至是遇到冲突问题时才想起用 sql 语句去解决。")]),a._v(" "),t("p",[a._v("由此,引发一些问题:")]),a._v(" "),t("ul",[t("li",[a._v("机器上的数据库是什么状态?")]),a._v(" "),t("li",[a._v("脚本到底生效没有?")]),a._v(" "),t("li",[a._v("生产环境修复的问题是否也在测试环境修复了?")]),a._v(" "),t("li",[a._v("如何建立一个新的数据库实例?")])]),a._v(" "),t("p",[a._v("数据迁移就是用来搞定这些混乱的问题:")]),a._v(" "),t("ul",[t("li",[a._v("通过草稿重建一个数据库。")]),a._v(" "),t("li",[a._v("在任何时候都可以清楚的了解数据库的状态。")]),a._v(" "),t("li",[a._v("以一种明确的方式将数据库从当前版本迁移到一个新版本。")])]),a._v(" "),t("h3",{attrs:{id:"flyway-如何工作"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#flyway-如何工作"}},[a._v("#")]),a._v(" Flyway 如何工作?")]),a._v(" "),t("p",[a._v("最简单的场景是指定 Flyway 迁移到一个空的数据库。")]),a._v(" "),t("p",[t("img",{attrs:{src:"http://upload-images.jianshu.io/upload_images/3101171-bb6e9f39e56ebbda.png",alt:"img"}})]),a._v(" "),t("p",[a._v("Flyway 会尝试查找它的 schema 历史表,如果数据库是空的,Flyway 就不再查找,而是直接创建数据库。")]),a._v(" "),t("p",[a._v("现再你就有了一个仅包含一张空表的数据库,默认情况下,这张表叫 "),t("strong",[a._v("flyway_schema_history")]),a._v("。")]),a._v(" "),t("p",[t("img",{attrs:{src:"http://upload-images.jianshu.io/upload_images/3101171-410eb31c6313b389.png",alt:"img"}})]),a._v(" "),t("p",[a._v("这张表将被用于追踪数据库的状态。")]),a._v(" "),t("p",[a._v("然后,Flyway 将开始扫描文件系统或应用 classpath 中的 "),t("strong",[a._v("migrations")]),a._v("。这些 "),t("strong",[a._v("migrations")]),a._v(" 可以是 sql 或 java。")]),a._v(" "),t("p",[a._v("这些 "),t("strong",[a._v("migrations")]),a._v(" 将根据他们的版本号进行排序。")]),a._v(" "),t("p",[t("img",{attrs:{src:"http://upload-images.jianshu.io/upload_images/3101171-d36ee07ada4efbcd.png",alt:"img"}})]),a._v(" "),t("p",[a._v("任意 migration 应用后,schema 历史表将更新。当元数据和初始状态替换后,可以称之为:迁移到新版本。")]),a._v(" "),t("p",[a._v("Flyway 一旦扫描了文件系统或应用 classpath 下的 migrations,这些 migrations 会检查 schema 历史表。如果它们的版本号低于或等于当前的版本,将被忽略。保留下来的 migrations 是等待的 migrations,有效但没有应用。")]),a._v(" "),t("p",[t("img",{attrs:{src:"http://upload-images.jianshu.io/upload_images/3101171-99a88fea7a31a070.png",alt:"img"}})]),a._v(" "),t("p",[a._v("migrations 将根据版本号排序并按序执行。")]),a._v(" "),t("p",[t("img",{attrs:{src:"http://upload-images.jianshu.io/upload_images/3101171-b444fef6e5c13b71.png",alt:"img"}})]),a._v(" "),t("h2",{attrs:{id:"快速上手"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#快速上手"}},[a._v("#")]),a._v(" 快速上手")]),a._v(" "),t("p",[a._v("Flyway 有 4 种使用方式:")]),a._v(" "),t("ul",[t("li",[a._v("命令行")]),a._v(" "),t("li",[a._v("JAVA API")]),a._v(" "),t("li",[a._v("Maven")]),a._v(" "),t("li",[a._v("Gradle")])]),a._v(" "),t("h3",{attrs:{id:"命令行"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#命令行"}},[a._v("#")]),a._v(" 命令行")]),a._v(" "),t("p",[a._v("适用于非 Java 用户,无需构建。")]),a._v(" "),t("div",{staticClass:"language-shell extra-class"},[t("pre",{pre:!0,attrs:{class:"language-shell"}},[t("code",[t("span",{pre:!0,attrs:{class:"token operator"}},[a._v(">")]),a._v(" flyway migrate "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[a._v("-url")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("..")]),a._v(". "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[a._v("-user")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("..")]),a._v(". "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[a._v("-password")]),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("..")]),a._v(".\n")])])]),t("p",[a._v("(1)"),t("strong",[a._v("下载解压")])]),a._v(" "),t("p",[a._v("进入"),t("a",{attrs:{href:"https://flywaydb.org/download/",target:"_blank",rel:"noopener noreferrer"}},[a._v("官方下载页面"),t("OutboundLink")],1),a._v(",选择合适版本,下载并解压到本地。")]),a._v(" "),t("p",[a._v("(2)"),t("strong",[a._v("配置 flyway")])]),a._v(" "),t("p",[a._v("编辑 "),t("code",[a._v("/conf/flyway.conf")]),a._v(":")]),a._v(" "),t("div",{staticClass:"language-properties extra-class"},[t("pre",{pre:!0,attrs:{class:"language-properties"}},[t("code",[t("span",{pre:!0,attrs:{class:"token key attr-name"}},[a._v("flyway.url")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),t("span",{pre:!0,attrs:{class:"token value attr-value"}},[a._v("jdbc:h2:file:./foobardb")]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token key attr-name"}},[a._v("flyway.user")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),t("span",{pre:!0,attrs:{class:"token value attr-value"}},[a._v("SA")]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token key attr-name"}},[a._v("flyway.password")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),a._v("\n")])])]),t("p",[a._v("(3)"),t("strong",[a._v("创建第一个 migration")])]),a._v(" "),t("p",[a._v("在 "),t("code",[a._v("/sql")]),a._v(" 目录下创建 "),t("code",[a._v("V1__Create_person_table.sql")]),a._v(" 文件,内容如下:")]),a._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("create")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("table")]),a._v(" PERSON "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("\n ID "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("int")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("not")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[a._v("null")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n NAME "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("varchar")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[a._v("100")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("not")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[a._v("null")]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n")])])]),t("p",[a._v("(4)"),t("strong",[a._v("迁移数据库")])]),a._v(" "),t("p",[a._v("运行 Flyway 来迁移数据库:")]),a._v(" "),t("div",{staticClass:"language-shell extra-class"},[t("pre",{pre:!0,attrs:{class:"language-shell"}},[t("code",[a._v("flyway-5.1."),t("span",{pre:!0,attrs:{class:"token operator"}},[t("span",{pre:!0,attrs:{class:"token file-descriptor important"}},[a._v("4")]),a._v(">")]),a._v(" flyway migrate\n")])])]),t("p",[a._v("运行正常的情况下,应该可以看到如下结果:")]),a._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[a._v('Database: jdbc:h2:file:./foobardb (H2 1.4)\nSuccessfully validated 1 migration (execution time 00:00.008s)\nCreating Schema History table: "PUBLIC"."flyway_schema_history"\nCurrent version of schema "PUBLIC": << Empty Schema >>\nMigrating schema "PUBLIC" to version 1 - Create person table\nSuccessfully applied 1 migration to schema "PUBLIC" (execution time 00:00.033s)\n')])])]),t("p",[a._v("(5)"),t("strong",[a._v("添加第二个 migration")])]),a._v(" "),t("p",[a._v("在 "),t("code",[a._v("/sql")]),a._v(" 目录下创建 "),t("code",[a._v("V2__Add_people.sql")]),a._v(" 文件,内容如下:")]),a._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("insert")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("into")]),a._v(" PERSON "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("ID"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" NAME"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("values")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[a._v("1")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[a._v("'Axel'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("insert")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("into")]),a._v(" PERSON "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("ID"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" NAME"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("values")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[a._v("2")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[a._v("'Mr. Foo'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("insert")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("into")]),a._v(" PERSON "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("ID"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" NAME"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("values")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[a._v("3")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[a._v("'Ms. Bar'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n")])])]),t("p",[a._v("运行 Flyway")]),a._v(" "),t("div",{staticClass:"language-shell extra-class"},[t("pre",{pre:!0,attrs:{class:"language-shell"}},[t("code",[a._v("flyway-5.1."),t("span",{pre:!0,attrs:{class:"token operator"}},[t("span",{pre:!0,attrs:{class:"token file-descriptor important"}},[a._v("4")]),a._v(">")]),a._v(" flyway migrate\n")])])]),t("p",[a._v("运行正常的情况下,应该可以看到如下结果:")]),a._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[a._v('Database: jdbc:h2:file:./foobardb (H2 1.4)\nSuccessfully validated 2 migrations (execution time 00:00.018s)\nCurrent version of schema "PUBLIC": 1\nMigrating schema "PUBLIC" to version 2 - Add people\nSuccessfully applied 1 migration to schema "PUBLIC" (execution time 00:00.016s)\n')])])]),t("h3",{attrs:{id:"java-api"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#java-api"}},[a._v("#")]),a._v(" JAVA API")]),a._v(" "),t("p",[a._v("(1)"),t("strong",[a._v("准备")])]),a._v(" "),t("ul",[t("li",[a._v("Java8+")]),a._v(" "),t("li",[a._v("Maven 3.x")])]),a._v(" "),t("p",[a._v("(2)"),t("strong",[a._v("添加依赖")])]),a._v(" "),t("p",[a._v("在 "),t("code",[a._v("pom.xml")]),a._v(" 中添加依赖:")]),a._v(" "),t("div",{staticClass:"language-xml extra-class"},[t("pre",{pre:!0,attrs:{class:"language-xml"}},[t("code",[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("project")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("...")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n ...\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("dependencies")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("dependency")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("groupId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("org.flywaydb"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("groupId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("artifactId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("flyway-core"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("artifactId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("version")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("5.1.4"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("version")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("dependency")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("dependency")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("groupId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("com.h2database"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("groupId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("artifactId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("h2"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("artifactId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("version")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("1.3.170"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("version")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("dependency")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n ...\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("dependencies")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n ...\n"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("project")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n")])])]),t("p",[a._v("(3)"),t("strong",[a._v("集成 Flyway")])]),a._v(" "),t("p",[a._v("添加 "),t("code",[a._v("App.java")]),a._v(" 文件,内容如下:")]),a._v(" "),t("div",{staticClass:"language-java extra-class"},[t("pre",{pre:!0,attrs:{class:"language-java"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("import")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token import"}},[t("span",{pre:!0,attrs:{class:"token namespace"}},[a._v("org"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),a._v("flywaydb"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),a._v("core"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")])]),t("span",{pre:!0,attrs:{class:"token class-name"}},[a._v("Flyway")])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("public")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("class")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token class-name"}},[a._v("App")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("public")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("static")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("void")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token function"}},[a._v("main")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),t("span",{pre:!0,attrs:{class:"token class-name"}},[a._v("String")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("[")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("]")]),a._v(" args"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("// Create the Flyway instance")]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token class-name"}},[a._v("Flyway")]),a._v(" flyway "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("new")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token class-name"}},[a._v("Flyway")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n\n "),t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("// Point it to the database")]),a._v("\n flyway"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),t("span",{pre:!0,attrs:{class:"token function"}},[a._v("setDataSource")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),t("span",{pre:!0,attrs:{class:"token string"}},[a._v('"jdbc:h2:file:./target/foobar"')]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[a._v('"sa"')]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("null")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n\n "),t("span",{pre:!0,attrs:{class:"token comment"}},[a._v("// Start the migration")]),a._v("\n flyway"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),t("span",{pre:!0,attrs:{class:"token function"}},[a._v("migrate")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),t("p",[a._v("(4)"),t("strong",[a._v("创建第一个 migration")])]),a._v(" "),t("p",[a._v("添加 "),t("code",[a._v("src/main/resources/db/migration/V1__Create_person_table.sql")]),a._v(" 文件,内容如下:")]),a._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("create")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("table")]),a._v(" PERSON "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("\n ID "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("int")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("not")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[a._v("null")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n NAME "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("varchar")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[a._v("100")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("not")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[a._v("null")]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n")])])]),t("p",[a._v("(5)"),t("strong",[a._v("执行程序")])]),a._v(" "),t("p",[a._v("执行 "),t("code",[a._v("App#main")]),a._v(":")]),a._v(" "),t("p",[a._v("运行正常的情况下,应该可以看到如下结果:")]),a._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[a._v('INFO: Creating schema history table: "PUBLIC"."flyway_schema_history"\nINFO: Current version of schema "PUBLIC": << Empty Schema >>\nINFO: Migrating schema "PUBLIC" to version 1 - Create person table\nINFO: Successfully applied 1 migration to schema "PUBLIC" (execution time 00:00.062s).\n')])])]),t("p",[a._v("(6)"),t("strong",[a._v("添加第二个 migration")])]),a._v(" "),t("p",[a._v("添加 src/main/resources/db/migration/V2__Add_people.sql 文件,内容如下:")]),a._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("insert")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("into")]),a._v(" PERSON "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("ID"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" NAME"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("values")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[a._v("1")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[a._v("'Axel'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("insert")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("into")]),a._v(" PERSON "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("ID"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" NAME"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("values")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[a._v("2")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[a._v("'Mr. Foo'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("insert")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("into")]),a._v(" PERSON "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("ID"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" NAME"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("values")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[a._v("3")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[a._v("'Ms. Bar'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n")])])]),t("p",[a._v("运行正常的情况下,应该可以看到如下结果:")]),a._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[a._v('INFO: Current version of schema "PUBLIC": 1\nINFO: Migrating schema "PUBLIC" to version 2 - Add people\nINFO: Successfully applied 1 migration to schema "PUBLIC" (execution time 00:00.090s).\n')])])]),t("h3",{attrs:{id:"maven"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#maven"}},[a._v("#")]),a._v(" Maven")]),a._v(" "),t("p",[a._v("与 Java API 方式大体相同,区别在 "),t("strong",[a._v("集成 Flyway")]),a._v(" 步骤:")]),a._v(" "),t("p",[a._v("Maven 方式使用插件来集成 Flyway:")]),a._v(" "),t("div",{staticClass:"language-xml extra-class"},[t("pre",{pre:!0,attrs:{class:"language-xml"}},[t("code",[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("project")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("xmlns")]),t("span",{pre:!0,attrs:{class:"token attr-value"}},[t("span",{pre:!0,attrs:{class:"token punctuation attr-equals"}},[a._v("=")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v('"')]),a._v("..."),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v('"')])]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n ...\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("build")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("plugins")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("plugin")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("groupId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("org.flywaydb"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("groupId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("artifactId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("flyway-maven-plugin"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("artifactId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("version")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("5.1.4"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("version")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("configuration")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("url")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("jdbc:h2:file:./target/foobar"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("url")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("user")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("sa"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("user")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("configuration")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("dependencies")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("dependency")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("groupId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("com.h2database"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("groupId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("artifactId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("h2"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("artifactId")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("version")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("1.4.191"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("version")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("dependency")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("dependencies")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("plugin")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("plugins")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("build")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token tag"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")]),a._v("project")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n")])])]),t("p",[a._v("因为用的是插件,所以执行方式不再是运行 Java 类,而是执行 maven 插件:")]),a._v(" "),t("div",{staticClass:"language-shell extra-class"},[t("pre",{pre:!0,attrs:{class:"language-shell"}},[t("code",[t("span",{pre:!0,attrs:{class:"token operator"}},[a._v(">")]),a._v(" mvn flyway:migrate\n")])])]),t("blockquote",[t("p",[a._v("👉 参考:"),t("a",{attrs:{href:"https://github.com/dunwu/Database/tree/master/codes/middleware/flyway",target:"_blank",rel:"noopener noreferrer"}},[a._v("示例源码"),t("OutboundLink")],1)])]),a._v(" "),t("h3",{attrs:{id:"gradle"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#gradle"}},[a._v("#")]),a._v(" Gradle")]),a._v(" "),t("p",[a._v("本人不用 Gradle,略。")]),a._v(" "),t("h2",{attrs:{id:"入门篇"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#入门篇"}},[a._v("#")]),a._v(" 入门篇")]),a._v(" "),t("h3",{attrs:{id:"概念"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#概念"}},[a._v("#")]),a._v(" 概念")]),a._v(" "),t("h4",{attrs:{id:"migrations"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#migrations"}},[a._v("#")]),a._v(" Migrations")]),a._v(" "),t("p",[a._v("在 Flyway 中,对于数据库的任何改变都称之为 "),t("strong",[a._v("Migrations")]),a._v("。")]),a._v(" "),t("p",[a._v("Migrations 可以分为 Versioned migrations 和 Repeatable migrations。")]),a._v(" "),t("p",[a._v("Versioned migrations 有 2 种形式:regular 和 undo。")]),a._v(" "),t("p",[a._v("Versioned migrations 和 Repeatable migrations 都可以使用 SQL 或 JAVA 来编写。")]),a._v(" "),t("h5",{attrs:{id:"versioned-migrations"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#versioned-migrations"}},[a._v("#")]),a._v(" Versioned migrations")]),a._v(" "),t("p",[a._v("由一个版本号(version)、一段描述(description)、一个校验(checksum)组成。版本号必须是惟一的。Versioned migrations 只能按顺序执行一次。")]),a._v(" "),t("p",[a._v("一般用于:")]),a._v(" "),t("ul",[t("li",[a._v("增删改 tables/indexes/foreign keys/enums/UDTs。")]),a._v(" "),t("li",[a._v("引用数据更新")]),a._v(" "),t("li",[a._v("用户数据校正")])]),a._v(" "),t("p",[a._v("Regular 示例:")]),a._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("CREATE")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("TABLE")]),a._v(" car "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("\n id "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("INT")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("NOT")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[a._v("NULL")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("PRIMARY")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("KEY")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n license_plate "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("VARCHAR")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("NOT")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[a._v("NULL")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n color "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("VARCHAR")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("NOT")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[a._v("NULL")]),a._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("ALTER")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("TABLE")]),a._v(" owner "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("ADD")]),a._v(" driver_license_id "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("VARCHAR")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("INSERT")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("INTO")]),a._v(" brand "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("name"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("VALUES")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),t("span",{pre:!0,attrs:{class:"token string"}},[a._v("'DeLorean'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n")])])]),t("h5",{attrs:{id:"undo-migrations"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#undo-migrations"}},[a._v("#")]),a._v(" Undo migrations")]),a._v(" "),t("blockquote",[t("p",[a._v("注:仅专业版支持")])]),a._v(" "),t("p",[a._v("Undo Versioned Migrations 负责撤销 Regular Versioned migrations 的影响。")]),a._v(" "),t("p",[a._v("Undo 示例:")]),a._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("DELETE")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("FROM")]),a._v(" brand "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("WHERE")]),a._v(" name"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[a._v("'DeLorean'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("ALTER")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("TABLE")]),a._v(" owner "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("DROP")]),a._v(" driver_license_id"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("DROP")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("TABLE")]),a._v(" car"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n")])])]),t("h5",{attrs:{id:"repeatable-migrations"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#repeatable-migrations"}},[a._v("#")]),a._v(" Repeatable migrations")]),a._v(" "),t("p",[a._v("由一段描述(description)、一个校验(checksum)组成。Versioned migrations 每次执行后,校验(checksum)会更新。")]),a._v(" "),t("p",[a._v("Repeatable migrations 用于管理可以通过一个文件来维护版本控制的数据库对象。")]),a._v(" "),t("p",[a._v("一般用于:")]),a._v(" "),t("ul",[t("li",[a._v("创建(重建)views/procedures/functions/packages 等。")]),a._v(" "),t("li",[a._v("大量引用数据重新插入")])]),a._v(" "),t("p",[a._v("示例:")]),a._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("CREATE")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("OR")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("REPLACE")]),a._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("VIEW")]),a._v(" blue_cars "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("AS")]),a._v("\n "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("SELECT")]),a._v(" id"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" license_plate "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("FROM")]),a._v(" cars "),t("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("WHERE")]),a._v(" color"),t("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[a._v("'blue'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n")])])]),t("h5",{attrs:{id:"基于-sql-的-migrations"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#基于-sql-的-migrations"}},[a._v("#")]),a._v(" 基于 SQL 的 migrations")]),a._v(" "),t("p",[a._v("migrations 最常用的编写形式就是 SQL。")]),a._v(" "),t("p",[a._v("基于 SQL 的 migrations 一般用于:")]),a._v(" "),t("ul",[t("li",[a._v("DDL 变更(针对 TABLES,VIEWS,TRIGGERS,SEQUENCES 等的 CREATE/ALTER/DROP 操作)")]),a._v(" "),t("li",[a._v("简单的引用数据变更(引用数据表中的 CRUD)")]),a._v(" "),t("li",[a._v("简单的大量数据变更(常规数据表中的 CRUD)")])]),a._v(" "),t("p",[t("strong",[a._v("命名规则")])]),a._v(" "),t("p",[a._v("为了被 Flyway 自动识别,SQL migrations 的文件命名必须遵循规定的模式:")]),a._v(" "),t("p",[t("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/flyway/sql-migrations.png",alt:"img"}})]),a._v(" "),t("ul",[t("li",[t("strong",[a._v("Prefix")]),a._v(" - "),t("code",[a._v("V")]),a._v(" 代表 versioned migrations (可配置), "),t("code",[a._v("U")]),a._v(" 代表 undo migrations (可配置)、 "),t("code",[a._v("R")]),a._v(" 代表 repeatable migrations (可配置)")]),a._v(" "),t("li",[t("strong",[a._v("Version")]),a._v(" - 版本号通过"),t("code",[a._v(".")]),a._v("(点)或"),t("code",[a._v("_")]),a._v("(下划线)分隔 (repeatable migrations 不需要)")]),a._v(" "),t("li",[t("strong",[a._v("Separator")]),a._v(" - "),t("code",[a._v("__")]),a._v(" (两个下划线) (可配置)")]),a._v(" "),t("li",[t("strong",[a._v("Description")]),a._v(" - 下划线或空格分隔的单词")]),a._v(" "),t("li",[t("strong",[a._v("Suffix")]),a._v(" - "),t("code",[a._v(".sql")]),a._v(" (可配置)")])]),a._v(" "),t("h5",{attrs:{id:"基于-java-的-migrations"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#基于-java-的-migrations"}},[a._v("#")]),a._v(" 基于 JAVA 的 migrations")]),a._v(" "),t("p",[a._v("基于 JAVA 的 migrations 适用于使用 SQL 不容易表达的场景:")]),a._v(" "),t("ul",[t("li",[a._v("BLOB 和 CLOB 变更")]),a._v(" "),t("li",[a._v("大量数据的高级变更(重新计算、高级格式变更)")])]),a._v(" "),t("p",[t("strong",[a._v("命名规则")])]),a._v(" "),t("p",[a._v("为了被 Flyway 自动识别,JAVA migrations 的文件命名必须遵循规定的模式:")]),a._v(" "),t("p",[t("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/flyway/java-migrations.png",alt:"img"}})]),a._v(" "),t("ul",[t("li",[t("strong",[a._v("Prefix")]),a._v(" - "),t("code",[a._v("V")]),a._v(" 代表 versioned migrations (可配置), "),t("code",[a._v("U")]),a._v(" 代表 undo migrations (可配置)、 "),t("code",[a._v("R")]),a._v(" 代表 repeatable migrations (可配置)")]),a._v(" "),t("li",[t("strong",[a._v("Version")]),a._v(" - 版本号通过"),t("code",[a._v(".")]),a._v("(点)或"),t("code",[a._v("_")]),a._v("(下划线)分隔 (repeatable migrations 不需要)")]),a._v(" "),t("li",[t("strong",[a._v("Separator")]),a._v(" - "),t("code",[a._v("__")]),a._v(" (两个下划线) (可配置)")]),a._v(" "),t("li",[t("strong",[a._v("Description")]),a._v(" - 下划线或空格分隔的单词")])]),a._v(" "),t("blockquote",[t("p",[a._v("👉 更多细节请参考:https://flywaydb.org/documentation/migrations")])]),a._v(" "),t("h4",{attrs:{id:"callbacks"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#callbacks"}},[a._v("#")]),a._v(" Callbacks")]),a._v(" "),t("blockquote",[t("p",[a._v("注:部分 events 仅专业版支持。")])]),a._v(" "),t("p",[a._v("尽管 Migrations 可能已经满足绝大部分场景的需要,但是某些情况下需要你一遍又一遍的执行相同的行为。这可能会重新编译存储过程,更新视图以及许多其他类型的开销。")]),a._v(" "),t("p",[a._v("因为以上原因,Flyway 提供了 Callbacks,用于在 Migrations 生命周期中添加钩子。")]),a._v(" "),t("p",[a._v("Callbacks 可以用 SQL 或 JAVA 来实现。")]),a._v(" "),t("h5",{attrs:{id:"sql-callbacks"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#sql-callbacks"}},[a._v("#")]),a._v(" SQL Callbacks")]),a._v(" "),t("p",[a._v("SQL Callbacks 的命名规则为:event 名 + SQL migration。")]),a._v(" "),t("p",[a._v("如: "),t("code",[a._v("beforeMigrate.sql")]),a._v(", "),t("code",[a._v("beforeEachMigrate.sql")]),a._v(", "),t("code",[a._v("afterEachMigrate.sql")]),a._v(" 等。")]),a._v(" "),t("p",[a._v("SQL Callbacks 也可以包含描述(description)。这种情况下,SQL Callbacks 文件名 = event 名 + 分隔符 + 描述 + 后缀。例:"),t("code",[a._v("beforeRepair__vacuum.sql")])]),a._v(" "),t("p",[a._v("当同一个 event 有多个 SQL callbacks,将按照它们描述(description)的顺序执行。")]),a._v(" "),t("blockquote",[t("p",[t("strong",[a._v("注:")]),a._v(" Flyway 也支持你配置的 "),t("code",[a._v("sqlMigrationSuffixes")]),a._v("。")])]),a._v(" "),t("h5",{attrs:{id:"java-callbacks"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#java-callbacks"}},[a._v("#")]),a._v(" JAVA Callbacks")]),a._v(" "),t("blockquote",[t("p",[a._v("当 SQL Callbacks 不够方便时,才应考虑 JAVA Callbacks。")])]),a._v(" "),t("p",[a._v("JAVA Callbacks 有 3 种形式:")]),a._v(" "),t("ol",[t("li",[t("strong",[a._v("基于 Java 的 Migrations")]),a._v(" - 实现 JdbcMigration、SpringJdbcMigration、MigrationInfoProvider、MigrationChecksumProvider、ConfigurationAware、FlywayConfiguration")]),a._v(" "),t("li",[t("strong",[a._v("基于 Java 的 Callbacks")]),a._v(" - 实现 org.flywaydb.core.api.callback 接口。")]),a._v(" "),t("li",[t("strong",[a._v("自定义 Migration resolvers 和 executors")]),a._v(" - 实现 MigrationResolver、MigrationExecutor、ConfigurationAware、FlywayConfiguration 接口。")])]),a._v(" "),t("blockquote",[t("p",[a._v("👉 更多细节请参考:https://flywaydb.org/documentation/callbacks")])]),a._v(" "),t("h4",{attrs:{id:"error-handlers"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#error-handlers"}},[a._v("#")]),a._v(" Error Handlers")]),a._v(" "),t("blockquote",[t("p",[a._v("注:仅专业版支持。")])]),a._v(" "),t("p",[a._v("(略)")]),a._v(" "),t("h4",{attrs:{id:"dry-runs"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#dry-runs"}},[a._v("#")]),a._v(" Dry Runs")]),a._v(" "),t("blockquote",[t("p",[a._v("注:仅专业版支持。")])]),a._v(" "),t("p",[a._v("(略)")]),a._v(" "),t("h3",{attrs:{id:"命令"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#命令"}},[a._v("#")]),a._v(" 命令")]),a._v(" "),t("p",[a._v("Flyway 的功能主要围绕着 7 个基本命令:"),t("a",{attrs:{href:"https://flywaydb.org/documentation/command/migrate",target:"_blank",rel:"noopener noreferrer"}},[a._v("Migrate"),t("OutboundLink")],1),a._v("、"),t("a",{attrs:{href:"https://flywaydb.org/documentation/command/clean",target:"_blank",rel:"noopener noreferrer"}},[a._v("Clean"),t("OutboundLink")],1),a._v("、"),t("a",{attrs:{href:"https://flywaydb.org/documentation/command/info",target:"_blank",rel:"noopener noreferrer"}},[a._v("Info"),t("OutboundLink")],1),a._v("、"),t("a",{attrs:{href:"https://flywaydb.org/documentation/command/validate",target:"_blank",rel:"noopener noreferrer"}},[a._v("Validate"),t("OutboundLink")],1),a._v("、"),t("a",{attrs:{href:"https://flywaydb.org/documentation/command/undo",target:"_blank",rel:"noopener noreferrer"}},[a._v("Undo"),t("OutboundLink")],1),a._v("、"),t("a",{attrs:{href:"https://flywaydb.org/documentation/command/baseline",target:"_blank",rel:"noopener noreferrer"}},[a._v("Baseline"),t("OutboundLink")],1),a._v(" 和 "),t("a",{attrs:{href:"https://flywaydb.org/documentation/command/repair",target:"_blank",rel:"noopener noreferrer"}},[a._v("Repair"),t("OutboundLink")],1),a._v("。")]),a._v(" "),t("p",[a._v("注:各命令的使用方法细节请查阅官方文档。")]),a._v(" "),t("h3",{attrs:{id:"支持的数据库"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#支持的数据库"}},[a._v("#")]),a._v(" 支持的数据库")]),a._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/oracle",target:"_blank",rel:"noopener noreferrer"}},[a._v("Oracle"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/sqlserver",target:"_blank",rel:"noopener noreferrer"}},[a._v("SQL Server"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/db2",target:"_blank",rel:"noopener noreferrer"}},[a._v("DB2"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/mysql",target:"_blank",rel:"noopener noreferrer"}},[a._v("MySQL"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/mariadb",target:"_blank",rel:"noopener noreferrer"}},[a._v("MariaDB"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/postgresql",target:"_blank",rel:"noopener noreferrer"}},[a._v("PostgreSQL"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/redshift",target:"_blank",rel:"noopener noreferrer"}},[a._v("Redshift"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/cockroachdb",target:"_blank",rel:"noopener noreferrer"}},[a._v("CockroachDB"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/saphana",target:"_blank",rel:"noopener noreferrer"}},[a._v("SAP HANA"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/sybasease",target:"_blank",rel:"noopener noreferrer"}},[a._v("Sybase ASE"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/informix",target:"_blank",rel:"noopener noreferrer"}},[a._v("Informix"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/h2",target:"_blank",rel:"noopener noreferrer"}},[a._v("H2"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/hsqldb",target:"_blank",rel:"noopener noreferrer"}},[a._v("HSQLDB"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/derby",target:"_blank",rel:"noopener noreferrer"}},[a._v("Derby"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://flywaydb.org/documentation/database/sqlite",target:"_blank",rel:"noopener noreferrer"}},[a._v("SQLite"),t("OutboundLink")],1)])]),a._v(" "),t("h2",{attrs:{id:"资料"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#资料"}},[a._v("#")]),a._v(" 资料")]),a._v(" "),t("p",[a._v("| "),t("a",{attrs:{href:"https://github.com/flyway/flyway",target:"_blank",rel:"noopener noreferrer"}},[a._v("Github"),t("OutboundLink")],1),a._v(" | "),t("a",{attrs:{href:"https://flywaydb.org/",target:"_blank",rel:"noopener noreferrer"}},[a._v("官方文档"),t("OutboundLink")],1),a._v(" |")]),a._v(" "),t("h2",{attrs:{id:"传送门"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#传送门"}},[a._v("#")]),a._v(" 🚪 传送门")]),a._v(" "),t("p",[a._v("| "),t("a",{attrs:{href:"https://dunwu.github.io/blog/",target:"_blank",rel:"noopener noreferrer"}},[a._v("钝悟的博客"),t("OutboundLink")],1),a._v(" | "),t("a",{attrs:{href:"https://github.com/dunwu/db-tutorial",target:"_blank",rel:"noopener noreferrer"}},[a._v("db-tutorial 首页"),t("OutboundLink")],1),a._v(" |")])])}),[],!1,null,null,null);t.default=e.exports}}]);
\ No newline at end of file
diff --git a/assets/js/11.5f47e5c7.js b/assets/js/11.5f47e5c7.js
new file mode 100644
index 00000000..bc9db99b
--- /dev/null
+++ b/assets/js/11.5f47e5c7.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{348:function(t,r,e){"use strict";e.r(r);var a=e(4),n=Object(a.a)({},(function(){var t=this,r=t._self._c;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h1",{attrs:{id:"数据库中间件和代理"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#数据库中间件和代理"}},[t._v("#")]),t._v(" 数据库中间件和代理")]),t._v(" "),r("h2",{attrs:{id:"📖-内容"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#📖-内容"}},[t._v("#")]),t._v(" 📖 内容")]),t._v(" "),r("ul",[r("li",[r("RouterLink",{attrs:{to:"/12.数据库/02.数据库中间件/01.Shardingsphere/01.ShardingSphere简介.html"}},[t._v("ShardingSphere 简介")])],1),t._v(" "),r("li",[r("RouterLink",{attrs:{to:"/12.数据库/02.数据库中间件/01.Shardingsphere/02.ShardingSphereJdbc.html"}},[t._v("ShardingSphere Jdbc")])],1),t._v(" "),r("li",[r("RouterLink",{attrs:{to:"/12.数据库/02.数据库中间件/02.Flyway.html"}},[t._v("版本管理中间件 Flyway")])],1)]),t._v(" "),r("h2",{attrs:{id:"📚-资料"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#📚-资料"}},[t._v("#")]),t._v(" 📚 资料")]),t._v(" "),r("ul",[r("li",[r("a",{attrs:{href:"https://github.com/seata/seata",target:"_blank",rel:"noopener noreferrer"}},[r("strong",[t._v("Seata")]),r("OutboundLink")],1),t._v(" - 分布式事务中间件。")]),t._v(" "),r("li",[r("a",{attrs:{href:"https://github.com/apache/shardingsphere",target:"_blank",rel:"noopener noreferrer"}},[r("strong",[t._v("ShardingSphere")]),r("OutboundLink")],1),t._v(" - 关系型数据库读写分离、分库分表中间件。")]),t._v(" "),r("li",[r("a",{attrs:{href:"https://github.com/flyway/flyway",target:"_blank",rel:"noopener noreferrer"}},[r("strong",[t._v("Flyway")]),r("OutboundLink")],1),t._v(" - 关系型数据库版本管理中间件。")]),t._v(" "),r("li",[r("a",{attrs:{href:"https://github.com/alibaba/canal",target:"_blank",rel:"noopener noreferrer"}},[r("strong",[t._v("Canal")]),r("OutboundLink")],1),t._v(" - 基于 MySQL 的 binlog,提供增量数据订阅和消费。")]),t._v(" "),r("li",[r("a",{attrs:{href:"https://github.com/twitter/twemproxy",target:"_blank",rel:"noopener noreferrer"}},[r("strong",[t._v("Twemproxy")]),r("OutboundLink")],1),t._v(" - Twitter 开源的一个 Redis 和 Memcache 的中间代理服务。")]),t._v(" "),r("li",[r("a",{attrs:{href:"https://github.com/CodisLabs/codis",target:"_blank",rel:"noopener noreferrer"}},[r("strong",[t._v("Codis")]),r("OutboundLink")],1),t._v(" - Redis 分布式集群方案。")])]),t._v(" "),r("h2",{attrs:{id:"🚪-传送"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#🚪-传送"}},[t._v("#")]),t._v(" 🚪 传送")]),t._v(" "),r("p",[t._v("◾ 💧 "),r("a",{attrs:{href:"https://dunwu.github.io/waterdrop/",target:"_blank",rel:"noopener noreferrer"}},[t._v("钝悟的 IT 知识图谱"),r("OutboundLink")],1),t._v(" ◾ 🎯 "),r("a",{attrs:{href:"https://dunwu.github.io/blog/",target:"_blank",rel:"noopener noreferrer"}},[t._v("钝悟的博客"),r("OutboundLink")],1),t._v(" ◾")])])}),[],!1,null,null,null);r.default=n.exports}}]);
\ No newline at end of file
diff --git a/assets/js/12.6d2ecf95.js b/assets/js/12.6d2ecf95.js
new file mode 100644
index 00000000..f240504e
--- /dev/null
+++ b/assets/js/12.6d2ecf95.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{349:function(t,a,e){"use strict";e.r(a);var _=e(4),v=Object(_.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"关系型数据库面试"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#关系型数据库面试"}},[t._v("#")]),t._v(" 关系型数据库面试")]),t._v(" "),a("h2",{attrs:{id:"索引和约束"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#索引和约束"}},[t._v("#")]),t._v(" 索引和约束")]),t._v(" "),a("h3",{attrs:{id:"什么是索引"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#什么是索引"}},[t._v("#")]),t._v(" 什么是索引")]),t._v(" "),a("p",[t._v("索引是对数据库表中一或多个列的值进行排序的结构,是帮助数据库高效查询数据的数据结构。")]),t._v(" "),a("h3",{attrs:{id:"索引的优缺点"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#索引的优缺点"}},[t._v("#")]),t._v(" 索引的优缺点")]),t._v(" "),a("p",[t._v("✔ 索引的优点:")]),t._v(" "),a("ul",[a("li",[t._v("索引大大减少了服务器需要扫描的数据量,从而加快检索速度。")]),t._v(" "),a("li",[t._v("支持行级锁的数据库,如 InnoDB 会在访问行的时候加锁。使用索引可以减少访问的行数,从而减少锁的竞争,提高并发。")]),t._v(" "),a("li",[t._v("索引可以帮助服务器避免排序和临时表。")]),t._v(" "),a("li",[t._v("索引可以将随机 I/O 变为顺序 I/O。")]),t._v(" "),a("li",[t._v("唯一索引可以确保每一行数据的唯一性,通过使用索引,可以在查询的过程中使用优化隐藏器,提高系统的性能。")])]),t._v(" "),a("p",[t._v("❌ 索引的缺点:")]),t._v(" "),a("ul",[a("li",[t._v("创建和维护索引要耗费时间,这会随着数据量的增加而增加。")]),t._v(" "),a("li",[a("strong",[t._v("索引需要占用额外的物理空间")]),t._v(",除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立组合索引那么需要的空间就会更大。")]),t._v(" "),a("li",[t._v("写操作("),a("code",[t._v("INSERT")]),t._v("/"),a("code",[t._v("UPDATE")]),t._v("/"),a("code",[t._v("DELETE")]),t._v(")时很可能需要更新索引,导致数据库的写操作性能降低。")])]),t._v(" "),a("h3",{attrs:{id:"何时使用索引"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#何时使用索引"}},[t._v("#")]),t._v(" 何时使用索引")]),t._v(" "),a("p",[t._v("索引能够轻易将查询性能提升几个数量级。")]),t._v(" "),a("p",[t._v("✔ 什么情况"),a("strong",[t._v("适用")]),t._v("索引:")]),t._v(" "),a("ul",[a("li",[t._v("表经常进行 "),a("code",[t._v("SELECT")]),t._v(" 操作;")]),t._v(" "),a("li",[t._v("表的数据量比较大;")]),t._v(" "),a("li",[t._v("列名经常出现在 "),a("code",[t._v("WHERE")]),t._v(" 或连接("),a("code",[t._v("JOIN")]),t._v(")条件中")])]),t._v(" "),a("p",[t._v("❌ 什么情况"),a("strong",[t._v("不适用")]),t._v("索引:")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("频繁写操作")]),t._v("( "),a("code",[t._v("INSERT")]),t._v("/"),a("code",[t._v("UPDATE")]),t._v("/"),a("code",[t._v("DELETE")]),t._v(" )- 需要更新索引空间;")]),t._v(" "),a("li",[a("strong",[t._v("非常小的表")]),t._v(" - 对于非常小的表,大部分情况下简单的全表扫描更高效。")]),t._v(" "),a("li",[t._v("列名不经常出现在 "),a("code",[t._v("WHERE")]),t._v(" 或连接("),a("code",[t._v("JOIN")]),t._v(")条件中 - 索引就会经常不命中,没有意义,还增加空间开销。")]),t._v(" "),a("li",[t._v("对于特大型表,建立和使用索引的代价将随之增长。可以考虑使用分区技术或 Nosql。")])]),t._v(" "),a("h3",{attrs:{id:"索引的类型"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#索引的类型"}},[t._v("#")]),t._v(" 索引的类型")]),t._v(" "),a("p",[t._v("主流的关系型数据库一般都支持以下索引类型:")]),t._v(" "),a("p",[t._v("从逻辑类型上划分(即一般创建表时设置的索引类型):")]),t._v(" "),a("ul",[a("li",[t._v("唯一索引("),a("code",[t._v("UNIQUE")]),t._v("):索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。")]),t._v(" "),a("li",[t._v("主键索引("),a("code",[t._v("PRIMARY")]),t._v("):一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般是在建表的时候同时创建主键索引。")]),t._v(" "),a("li",[t._v("普通索引("),a("code",[t._v("INDEX")]),t._v("):最基本的索引,没有任何限制。")]),t._v(" "),a("li",[t._v("组合索引:多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合。")])]),t._v(" "),a("p",[t._v("从物理存储上划分:")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("聚集索引")]),t._v("("),a("code",[t._v("Clustered")]),t._v("):表中各行的物理顺序与键值的逻辑(索引)顺序相同,每个表只能有一个。")]),t._v(" "),a("li",[a("strong",[t._v("非聚集索引")]),t._v("("),a("code",[t._v("Non-clustered")]),t._v("):非聚集索引指定表的逻辑顺序,也可以视为二级索引。数据存储在一个位置,索引存储在另一个位置,索引中包含指向数据存储位置的指针。可以有多个,小于 249 个。")])]),t._v(" "),a("h3",{attrs:{id:"索引的数据结构"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#索引的数据结构"}},[t._v("#")]),t._v(" 索引的数据结构")]),t._v(" "),a("p",[t._v("主流数据库的索引一般使用的数据结构为:B 树、B+ 树。")]),t._v(" "),a("h4",{attrs:{id:"b-树"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#b-树"}},[t._v("#")]),t._v(" B 树")]),t._v(" "),a("p",[t._v("一棵 M 阶的 B-Tree 满足以下条件:")]),t._v(" "),a("ul",[a("li",[t._v("每个结点至多有 M 个孩子;")]),t._v(" "),a("li",[t._v("除根结点和叶结点外,其它每个结点至少有 M/2 个孩子;")]),t._v(" "),a("li",[t._v("根结点至少有两个孩子(除非该树仅包含一个结点);")]),t._v(" "),a("li",[t._v("所有叶结点在同一层,叶结点不包含任何关键字信息;")]),t._v(" "),a("li",[t._v("有 K 个关键字的非叶结点恰好包含 K+1 个孩子;")])]),t._v(" "),a("p",[t._v("对于任意结点,其内部的关键字 Key 是升序排列的。每个节点中都包含了 data。")]),t._v(" "),a("div",{attrs:{align:"center"}},[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/RDB/B-TREE.png"}})]),t._v(" "),a("p",[t._v("对于每个结点,主要包含一个关键字数组 "),a("code",[t._v("Key[]")]),t._v(",一个指针数组(指向儿子)"),a("code",[t._v("Son[]")]),t._v("。")]),t._v(" "),a("p",[t._v("在 B-Tree 内,查找的流程是:")]),t._v(" "),a("ol",[a("li",[t._v("使用顺序查找(数组长度较短时)或折半查找方法查找 Key[] 数组,若找到关键字 K,则返回该结点的地址及 K 在 Key[] 中的位置;")]),t._v(" "),a("li",[t._v("否则,可确定 K 在某个 Key[i] 和 Key[i+1] 之间,则从 Son[i] 所指的子结点继续查找,直到在某结点中查找成功;")]),t._v(" "),a("li",[t._v("或直至找到叶结点且叶结点中的查找仍不成功时,查找过程失败。")])]),t._v(" "),a("h4",{attrs:{id:"b-树-2"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#b-树-2"}},[t._v("#")]),t._v(" B+ 树")]),t._v(" "),a("p",[t._v("B+Tree 是 B-Tree 的变种:")]),t._v(" "),a("ul",[a("li",[t._v("每个节点的指针上限为 2d 而不是 2d+1(d 为节点的出度)。")]),t._v(" "),a("li",[t._v("非叶子节点不存储 data,只存储 key;叶子节点不存储指针。")])]),t._v(" "),a("div",{attrs:{align:"center"}},[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/RDB/B+TREE.png"}})]),t._v(" "),a("p",[t._v("由于并不是所有节点都具有相同的域,因此 B+Tree 中叶节点和内节点一般大小不同。这点与 B-Tree 不同,虽然 B-Tree 中不同节点存放的 key 和指针可能数量不一致,但是每个节点的域和上限是一致的,所以在实现中 B-Tree 往往对每个节点申请同等大小的空间。")]),t._v(" "),a("p",[a("strong",[t._v("带有顺序访问指针的 B+Tree")])]),t._v(" "),a("p",[t._v("一般在数据库系统或文件系统中使用的 B+Tree 结构都在经典 B+Tree 的基础上进行了优化,增加了顺序访问指针。")]),t._v(" "),a("div",{attrs:{align:"center"}},[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/RDB/带有顺序访问指针的B+Tree.png"}})]),t._v(" "),a("p",[t._v("在 B+Tree 的每个叶子节点增加一个指向相邻叶子节点的指针,就形成了带有顺序访问指针的 B+Tree。")]),t._v(" "),a("p",[t._v("这个优化的目的是为了提高区间访问的性能,例如上图中如果要查询 key 为从 18 到 49 的所有数据记录,当找到 18 后,只需顺着节点和指针顺序遍历就可以一次性访问到所有数据节点,极大提到了区间查询效率。")]),t._v(" "),a("h4",{attrs:{id:"b-树-vs-b-树"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#b-树-vs-b-树"}},[t._v("#")]),t._v(" B 树 vs. B+ 树")]),t._v(" "),a("ul",[a("li",[t._v("B+ 树更适合外部存储(一般指磁盘存储),由于内节点(非叶子节点)不存储 data,所以一个节点可以存储更多的内节点,每个节点能索引的范围更大更精确。也就是说使用 B+ 树单次磁盘 IO 的信息量相比较 B 树更大,IO 效率更高。")]),t._v(" "),a("li",[t._v("Mysql 是关系型数据库,经常会按照区间来访问某个索引列,B+ 树的叶子节点间按顺序建立了链指针,加强了区间访问性,所以 B+ 树对索引列上的区间范围查询很友好。而 B 树每个节点的 key 和 data 在一起,无法进行区间查找。")])]),t._v(" "),a("h4",{attrs:{id:"hash"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#hash"}},[t._v("#")]),t._v(" Hash")]),t._v(" "),a("blockquote",[a("p",[t._v("Hash 索引只有精确匹配索引所有列的查询才有效。")])]),t._v(" "),a("p",[t._v("对于每一行数据,对所有的索引列计算一个 "),a("code",[t._v("hashcode")]),t._v("。哈希索引将所有的 "),a("code",[t._v("hashcode")]),t._v(" 存储在索引中,同时在 Hash 表中保存指向每个数据行的指针。")]),t._v(" "),a("p",[t._v("哈希结构索引的优点:")]),t._v(" "),a("ul",[a("li",[t._v("因为索引数据结构紧凑,所以查询速度非常快。")])]),t._v(" "),a("p",[t._v("哈希结构索引的缺点:")]),t._v(" "),a("ul",[a("li",[t._v("哈希索引数据不是按照索引值顺序存储的,所以无法用于排序。")]),t._v(" "),a("li",[t._v("哈希索引不支持部分索引匹配查找。如,在数据列 (A,B) 上建立哈希索引,如果查询只有数据列 A,无法使用该索引。")]),t._v(" "),a("li",[t._v("哈希索引只支持等值比较查询,不支持任何范围查询,如 WHERE price > 100。")]),t._v(" "),a("li",[t._v("哈希索引有可能出现哈希冲突,出现哈希冲突时,必须遍历链表中所有的行指针,逐行比较,直到找到符合条件的行。")])]),t._v(" "),a("h3",{attrs:{id:"索引策略"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#索引策略"}},[t._v("#")]),t._v(" 索引策略")]),t._v(" "),a("h4",{attrs:{id:"索引基本原则"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#索引基本原则"}},[t._v("#")]),t._v(" 索引基本原则")]),t._v(" "),a("ul",[a("li",[t._v("索引不是越多越好,不要为所有列都创建索引。")]),t._v(" "),a("li",[t._v("要尽量避免冗余和重复索引;")]),t._v(" "),a("li",[t._v("要考虑删除未使用的索引;")]),t._v(" "),a("li",[t._v("尽量的扩展索引,不要新建索引;")]),t._v(" "),a("li",[t._v("频繁作为 "),a("code",[t._v("WHERE")]),t._v(" 过滤条件的列应该考虑添加索引")])]),t._v(" "),a("h4",{attrs:{id:"独立的列"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#独立的列"}},[t._v("#")]),t._v(" 独立的列")]),t._v(" "),a("p",[a("strong",[t._v("如果查询中的列不是独立的列,则数据库不会使用索引")]),t._v("。")]),t._v(" "),a("p",[t._v("“独立的列” 是指索引列不能是表达式的一部分,也不能是函数的参数。")]),t._v(" "),a("p",[t._v("❌ 错误示例:")]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" actor_id "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" actor "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" actor_id "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" TO_DAYS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("current_date")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" TO_DAYS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("date_col"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("h4",{attrs:{id:"前缀索引和索引选择性"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#前缀索引和索引选择性"}},[t._v("#")]),t._v(" 前缀索引和索引选择性")]),t._v(" "),a("p",[t._v("有时候需要索引很长的字符列,这会让索引变得大且慢。")]),t._v(" "),a("p",[t._v("解决方法是:可以索引开始的部分字符,这样可以大大节约索引空间,从而提高索引效率。但这样也会降低索引的选择性。")]),t._v(" "),a("p",[t._v("索引的选择性是指:不重复的索引值和数据表记录总数的比值。最大值为 1,此时每个记录都有唯一的索引与其对应。选择性越高,查询效率也越高。")]),t._v(" "),a("p",[t._v("对于 BLOB/TEXT/VARCHAR 这种文本类型的列,必须使用前缀索引,因为数据库往往不允许索引这些列的完整长度。")]),t._v(" "),a("p",[t._v("要选择足够长的前缀以保证较高的选择性,同时又不能太长(节约空间)。")]),t._v(" "),a("p",[t._v("❌ 低效示例:")]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("COUNT")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("AS")]),t._v(" cnt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" city "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" sakila"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("city_demo\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("GROUP")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("BY")]),t._v(" city "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ORDER")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("BY")]),t._v(" cnt "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DESC")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("LIMIT")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("✔ 高效示例:")]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("COUNT")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("AS")]),t._v(" cnt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("LEFT")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("city"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("AS")]),t._v(" pref "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" sakila"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("city_demo\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("GROUP")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("BY")]),t._v(" city "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ORDER")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("BY")]),t._v(" cnt "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DESC")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("LIMIT")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("h4",{attrs:{id:"多列索引"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#多列索引"}},[t._v("#")]),t._v(" 多列索引")]),t._v(" "),a("p",[a("strong",[t._v("不要为每个列都创建独立索引")]),t._v("。")]),t._v(" "),a("p",[a("strong",[t._v("将选择性高的列或基数大的列优先排在多列索引最前列")]),t._v("。但有时,也需要考虑 WHERE 子句中的排序、分组和范围条件等因素,这些因素也会对查询性能造成较大影响。")]),t._v(" "),a("p",[t._v("举例来说,有一张 user 表,其中含 name, sex, age 三个列,如果将这三者组合为多列索引,应该用什么样的顺序呢?从选择性高的角度来看:"),a("code",[t._v("name > age > sex")]),t._v("。")]),t._v(" "),a("h4",{attrs:{id:"聚簇索引"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#聚簇索引"}},[t._v("#")]),t._v(" 聚簇索引")]),t._v(" "),a("p",[t._v("聚簇索引不是一种单独的索引类型,而是一种数据存储方式。具体细节依赖于实现方式。如 "),a("strong",[t._v("InnoDB 的聚簇索引实际是在同一个结构中保存了 B 树的索引和数据行")]),t._v("。")]),t._v(" "),a("p",[a("strong",[t._v("聚簇表示数据行和相邻的键值紧凑地存储在一起,因为数据紧凑,所以访问快")]),t._v("。因为无法同时把数据行存放在两个不同的地方,所以"),a("strong",[t._v("一个表只能有一个聚簇索引")]),t._v("。")]),t._v(" "),a("p",[t._v("若没有定义主键,InnoDB 会隐式定义一个主键来作为聚簇索引。")]),t._v(" "),a("h4",{attrs:{id:"覆盖索引"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#覆盖索引"}},[t._v("#")]),t._v(" 覆盖索引")]),t._v(" "),a("p",[t._v("索引包含所有需要查询的字段的值。")]),t._v(" "),a("p",[t._v("具有以下优点:")]),t._v(" "),a("ul",[a("li",[t._v("因为索引条目通常远小于数据行的大小,所以若只读取索引,能大大减少数据访问量。")]),t._v(" "),a("li",[t._v("一些存储引擎(例如 MyISAM)在内存中只缓存索引,而数据依赖于操作系统来缓存。因此,只访问索引可以不使用系统调用(通常比较费时)。")]),t._v(" "),a("li",[t._v("对于 InnoDB 引擎,若辅助索引能够覆盖查询,则无需访问主索引。")])]),t._v(" "),a("h4",{attrs:{id:"使用索引扫描来做排序"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#使用索引扫描来做排序"}},[t._v("#")]),t._v(" 使用索引扫描来做排序")]),t._v(" "),a("p",[t._v("Mysql 有两种方式可以生成排序结果:通过排序操作;或者按索引顺序扫描。")]),t._v(" "),a("p",[a("strong",[t._v("索引最好既满足排序,又用于查找行")]),t._v("。这样,就可以使用索引来对结果排序。")]),t._v(" "),a("h4",{attrs:{id:"最左前缀匹配原则"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#最左前缀匹配原则"}},[t._v("#")]),t._v(" 最左前缀匹配原则")]),t._v(" "),a("p",[t._v("MySQL 会一直向右匹配直到遇到范围查询 "),a("code",[t._v("(>,<,BETWEEN,LIKE)")]),t._v(" 就停止匹配。")]),t._v(" "),a("ul",[a("li",[t._v("索引可以简单如一个列(a),也可以复杂如多个列(a, b, c, d),即"),a("strong",[t._v("联合索引")]),t._v("。")]),t._v(" "),a("li",[t._v("如果是联合索引,那么 key 也由多个列组成,同时,索引只能用于查找 key 是否"),a("strong",[t._v("存在(相等)")]),t._v(",遇到范围查询(>、<、between、like 左匹配)等就"),a("strong",[t._v("不能进一步匹配")]),t._v("了,后续退化为线性查找。")]),t._v(" "),a("li",[t._v("因此,"),a("strong",[t._v("列的排列顺序决定了可命中索引的列数")]),t._v("。")])]),t._v(" "),a("p",[t._v("例子:")]),t._v(" "),a("ul",[a("li",[t._v("如有索引(a, b, c, d),查询条件 a = 1 and b = 2 and c > 3 and d = 4,则会在每个节点依次命中 a、b、c,无法命中 d。(很简单:索引命中只能是"),a("strong",[t._v("相等")]),t._v("的情况,不能是范围匹配)")])]),t._v(" "),a("h4",{attrs:{id:"和-in-可以乱序"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#和-in-可以乱序"}},[t._v("#")]),t._v(" = 和 in 可以乱序")]),t._v(" "),a("p",[a("strong",[t._v("不需要考虑=、in 等的顺序")]),t._v(",Mysql 会自动优化这些条件的顺序,以匹配尽可能多的索引列。")]),t._v(" "),a("p",[t._v("例子:如有索引(a, b, c, d),查询条件 c > 3 and b = 2 and a = 1 and d < 4 与 a = 1 and c > 3 and b = 2 and d < 4 等顺序都是可以的,MySQL 会自动优化为 a = 1 and b = 2 and c > 3 and d < 4,依次命中 a、b、c。")]),t._v(" "),a("h3",{attrs:{id:"约束"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#约束"}},[t._v("#")]),t._v(" 约束")]),t._v(" "),a("p",[t._v("数据库约束("),a("code",[t._v("CONSTRAINT")]),t._v(")有哪些:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("NOT NULL")]),t._v(" - 用于控制字段的内容一定不能为空(NULL)。")]),t._v(" "),a("li",[a("code",[t._v("UNIQUE")]),t._v(" - 字段内容不能重复,一个表允许有多个 "),a("code",[t._v("Unique")]),t._v(" 约束。")]),t._v(" "),a("li",[a("code",[t._v("PRIMARY KEY")]),t._v(" - 数据表中对储存数据对象予以唯一和完整标识的数据列或属性的组合,它在一个表中只允许有一个。主键的取值不能为空值(Null)。")]),t._v(" "),a("li",[a("code",[t._v("FOREIGN KEY")]),t._v(" - 在一个表中存在的另一个表的主键称此表的外键。用于预防破坏表之间连接的动作,也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。")]),t._v(" "),a("li",[a("code",[t._v("CHECK")]),t._v(" - 用于控制字段的值范围。")])]),t._v(" "),a("h2",{attrs:{id:"并发控制"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#并发控制"}},[t._v("#")]),t._v(" 并发控制")]),t._v(" "),a("h3",{attrs:{id:"乐观锁和悲观锁"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#乐观锁和悲观锁"}},[t._v("#")]),t._v(" 乐观锁和悲观锁")]),t._v(" "),a("blockquote",[a("ul",[a("li",[t._v("数据库的乐观锁和悲观锁是什么?")]),t._v(" "),a("li",[t._v("数据库的乐观锁和悲观锁如何实现?")])])]),t._v(" "),a("p",[t._v("确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性,"),a("strong",[t._v("乐观锁和悲观锁是并发控制主要采用的技术手段。")])]),t._v(" "),a("ul",[a("li",[a("strong",[a("code",[t._v("悲观锁")])]),t._v(" - 假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作\n"),a("ul",[a("li",[a("strong",[t._v("在查询完数据的时候就把事务锁起来,直到提交事务(COMMIT)")])]),t._v(" "),a("li",[t._v("实现方式:使用数据库中的锁机制")])])]),t._v(" "),a("li",[a("strong",[a("code",[t._v("乐观锁")])]),t._v(" - 假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。\n"),a("ul",[a("li",[a("strong",[t._v("在修改数据的时候把事务锁起来,通过 version 的方式来进行锁定")])]),t._v(" "),a("li",[t._v("实现方式:使用 version 版本或者时间戳")])])])]),t._v(" "),a("h3",{attrs:{id:"行级锁和表级锁"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#行级锁和表级锁"}},[t._v("#")]),t._v(" 行级锁和表级锁")]),t._v(" "),a("blockquote",[a("ul",[a("li",[t._v("什么是行级锁和表级锁?")]),t._v(" "),a("li",[t._v("什么时候用行级锁?什么时候用表级锁?")])])]),t._v(" "),a("p",[t._v("从数据库的锁粒度来看,MySQL 中提供了两种封锁粒度:行级锁和表级锁。")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("表级锁(table lock)")]),t._v(" - 锁定整张表。用户对表进行写操作前,需要先获得写锁,这会阻塞其他用户对该表的所有读写操作。只有没有写锁时,其他用户才能获得读锁,读锁之间不会相互阻塞。")]),t._v(" "),a("li",[a("strong",[t._v("行级锁(row lock)")]),t._v(" - 仅对指定的行记录进行加锁,这样其它进程还是可以对同一个表中的其它记录进行操作。")])]),t._v(" "),a("p",[t._v("二者需要权衡:")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("锁定的数据量越少,锁竞争的发生频率就越小,系统的并发程度就越高")]),t._v("。")]),t._v(" "),a("li",[a("strong",[t._v("锁粒度越小,系统开销就越大")]),t._v("。")])]),t._v(" "),a("p",[t._v("在 "),a("code",[t._v("InnoDB")]),t._v(" 中,行锁是通过给索引上的索引项加锁来实现的。"),a("strong",[t._v("如果没有索引,"),a("code",[t._v("InnoDB")]),t._v(" 将会通过隐藏的聚簇索引来对记录加锁")]),t._v("。")]),t._v(" "),a("h3",{attrs:{id:"读写锁"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#读写锁"}},[t._v("#")]),t._v(" 读写锁")]),t._v(" "),a("blockquote",[a("ul",[a("li",[t._v("什么是读写锁?")])])]),t._v(" "),a("ul",[a("li",[t._v("独享锁(Exclusive),简写为 X 锁,又称写锁。使用方式:"),a("code",[t._v("SELECT ... FOR UPDATE;")])]),t._v(" "),a("li",[t._v("共享锁(Shared),简写为 S 锁,又称读锁。使用方式:"),a("code",[t._v("SELECT ... LOCK IN SHARE MODE;")])])]),t._v(" "),a("p",[t._v("写锁和读锁的关系,简言之:"),a("strong",[t._v("独享锁存在,其他事务就不能做任何操作")]),t._v("。")]),t._v(" "),a("p",[a("strong",[a("code",[t._v("InnoDB")]),t._v(" 下的行锁、间隙锁、next-key 锁统统属于独享锁")]),t._v("。")]),t._v(" "),a("h3",{attrs:{id:"意向锁"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#意向锁"}},[t._v("#")]),t._v(" 意向锁")]),t._v(" "),a("blockquote",[a("ul",[a("li",[t._v("什么是意向锁?")]),t._v(" "),a("li",[t._v("意向锁有什么用?")])])]),t._v(" "),a("p",[t._v("意向锁的作用是:"),a("strong",[t._v("当存在表级锁和行级锁的情况下,必须先申请意向锁(表级锁,但不是真的加锁),再获取行级锁")]),t._v("。使用意向锁(Intention Locks)可以更容易地支持多粒度封锁。")]),t._v(" "),a("p",[a("strong",[t._v("意向锁是 "),a("code",[t._v("InnoDB")]),t._v(" 自动加的,不需要用户干预")]),t._v("。")]),t._v(" "),a("h3",{attrs:{id:"mvcc"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#mvcc"}},[t._v("#")]),t._v(" MVCC")]),t._v(" "),a("blockquote",[a("p",[t._v("什么是 MVCC?")]),t._v(" "),a("p",[t._v("MVCC 有什么用?解决了什么问题?")]),t._v(" "),a("p",[t._v("MVCC 的原理是什么?")])]),t._v(" "),a("p",[t._v("多版本并发控制(Multi-Version Concurrency Control, MVCC)是 "),a("code",[t._v("InnoDB")]),t._v(" 存储引擎实现隔离级别的一种具体方式,"),a("strong",[t._v("用于实现提交读和可重复读这两种隔离级别")]),t._v("。而未提交读隔离级别总是读取最新的数据行,要求很低,无需使用 MVCC。可串行化隔离级别需要对所有读取的行都加锁,单纯使用 MVCC 无法实现。")]),t._v(" "),a("p",[t._v("MVCC 的思想是:")]),t._v(" "),a("ul",[a("li",[t._v("保存数据在某个时间点的快照。"),a("strong",[t._v("写操作(DELETE、INSERT、UPDATE)更新最新的版本快照,而读操作去读旧版本快照,没有互斥关系")]),t._v(",这一点和 "),a("code",[t._v("CopyOnWrite")]),t._v(" 类似。")]),t._v(" "),a("li",[t._v("脏读和不可重复读最根本的原因是"),a("strong",[t._v("事务读取到其它事务未提交的修改")]),t._v("。在事务进行读取操作时,为了解决脏读和不可重复读问题,"),a("strong",[t._v("MVCC 规定只能读取已经提交的快照")]),t._v("。当然一个事务可以读取自身未提交的快照,这不算是脏读。")])]),t._v(" "),a("h3",{attrs:{id:"next-key-锁"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#next-key-锁"}},[t._v("#")]),t._v(" Next-key 锁")]),t._v(" "),a("p",[t._v("Next-Key 锁是 MySQL 的 "),a("code",[t._v("InnoDB")]),t._v(" 存储引擎的一种锁实现。")]),t._v(" "),a("p",[t._v("MVCC 不能解决幻读问题,"),a("strong",[t._v("Next-Key 锁就是为了解决幻读问题")]),t._v("。在可重复读("),a("code",[t._v("REPEATABLE READ")]),t._v(")隔离级别下,使用 "),a("strong",[t._v("MVCC + Next-Key 锁")]),t._v(" 可以解决幻读问题。")]),t._v(" "),a("p",[t._v("另外,根据针对 SQL 语句检索条件的不同,加锁又有以下三种情形需要我们掌握。")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("Record Lock")]),t._v(" - "),a("strong",[t._v("行锁对索引项加锁,若没有索引则使用表锁")]),t._v("。")]),t._v(" "),a("li",[a("code",[t._v("Gap Lock")]),t._v(" - 对索引项之间的间隙加锁。锁定索引之间的间隙,但是不包含索引本身。例如当一个事务执行以下语句,其它事务就不能在 t.c 中插入 15。"),a("code",[t._v("SELECT c FROM t WHERE c BETWEEN 10 and 20 FOR UPDATE;")])]),t._v(" "),a("li",[a("code",[t._v("Next-key lock")]),t._v(" -它是 "),a("code",[t._v("Record Lock")]),t._v(" 和 "),a("code",[t._v("Gap Lock")]),t._v(" 的结合,不仅锁定一个记录上的索引,也锁定索引之间的间隙。它锁定一个前开后闭区间。")])]),t._v(" "),a("p",[t._v("索引分为主键索引和非主键索引两种,如果一条 SQL 语句操作了主键索引,MySQL 就会锁定这条主键索引;如果一条语句操作了非主键索引,MySQL 会先锁定该非主键索引,再锁定相关的主键索引。在 "),a("code",[t._v("UPDATE")]),t._v("、"),a("code",[t._v("DELETE")]),t._v(" 操作时,MySQL 不仅锁定 "),a("code",[t._v("WHERE")]),t._v(" 条件扫描过的所有索引记录,而且会锁定相邻的键值,即所谓的 "),a("code",[t._v("next-key lock")]),t._v("。")]),t._v(" "),a("p",[t._v("当两个事务同时执行,一个锁住了主键索引,在等待其他相关索引。另一个锁定了非主键索引,在等待主键索引。这样就会发生死锁。发生死锁后,"),a("code",[t._v("InnoDB")]),t._v(" 一般都可以检测到,并使一个事务释放锁回退,另一个获取锁完成事务。")]),t._v(" "),a("h2",{attrs:{id:"事务"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#事务"}},[t._v("#")]),t._v(" 事务")]),t._v(" "),a("blockquote",[a("p",[t._v("事务简单来说:"),a("strong",[t._v("一个 Session 中所进行所有的操作,要么同时成功,要么同时失败")]),t._v("。具体来说,事务指的是满足 ACID 特性的一组操作,可以通过 "),a("code",[t._v("Commit")]),t._v(" 提交一个事务,也可以使用 "),a("code",[t._v("Rollback")]),t._v(" 进行回滚。")])]),t._v(" "),a("p",[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/RDB/%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BA%8B%E5%8A%A1.png",alt:"img"}})]),t._v(" "),a("h3",{attrs:{id:"acid"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#acid"}},[t._v("#")]),t._v(" ACID")]),t._v(" "),a("p",[t._v("ACID — 数据库事务正确执行的四个基本要素:")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("原子性(Atomicity)")])]),t._v(" "),a("li",[a("strong",[t._v("一致性(Consistency)")])]),t._v(" "),a("li",[a("strong",[t._v("隔离性(Isolation)")])]),t._v(" "),a("li",[a("strong",[t._v("持久性(Durability)")])])]),t._v(" "),a("p",[a("strong",[t._v("一个支持事务(Transaction)中的数据库系统,必需要具有这四种特性,否则在事务过程(Transaction processing)当中无法保证数据的正确性,交易过程极可能达不到交易。")])]),t._v(" "),a("p",[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/RDB/%E6%95%B0%E6%8D%AE%E5%BA%93ACID.png",alt:"img"}})]),t._v(" "),a("h3",{attrs:{id:"并发一致性问题"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#并发一致性问题"}},[t._v("#")]),t._v(" 并发一致性问题")]),t._v(" "),a("p",[t._v("在并发环境下,事务的隔离性很难保证,因此会出现很多并发一致性问题。")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("丢失修改")])])]),t._v(" "),a("p",[t._v("T"),a("sub",[t._v("1")]),t._v(" 和 T"),a("sub",[t._v("2")]),t._v(" 两个事务都对一个数据进行修改,T"),a("sub",[t._v("1")]),t._v(" 先修改,T"),a("sub",[t._v("2")]),t._v(" 随后修改,T"),a("sub",[t._v("2")]),t._v(" 的修改覆盖了 T"),a("sub",[t._v("1")]),t._v(" 的修改。")]),t._v(" "),a("p",[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/RDB/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%B9%B6%E5%8F%91%E4%B8%80%E8%87%B4%E6%80%A7-%E4%B8%A2%E5%A4%B1%E4%BF%AE%E6%94%B9.png",alt:"img"}})]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("脏读")])])]),t._v(" "),a("p",[t._v("T"),a("sub",[t._v("1")]),t._v(" 修改一个数据,T"),a("sub",[t._v("2")]),t._v(" 随后读取这个数据。如果 T"),a("sub",[t._v("1")]),t._v(" 撤销了这次修改,那么 T"),a("sub",[t._v("2")]),t._v(" 读取的数据是脏数据。")]),t._v(" "),a("p",[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/RDB/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%B9%B6%E5%8F%91%E4%B8%80%E8%87%B4%E6%80%A7-%E8%84%8F%E6%95%B0%E6%8D%AE.png",alt:"img"}})]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("不可重复读")])])]),t._v(" "),a("p",[t._v("T"),a("sub",[t._v("2")]),t._v(" 读取一个数据,T"),a("sub",[t._v("1")]),t._v(" 对该数据做了修改。如果 T"),a("sub",[t._v("2")]),t._v(" 再次读取这个数据,此时读取的结果和第一次读取的结果不同。")]),t._v(" "),a("p",[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/RDB/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%B9%B6%E5%8F%91%E4%B8%80%E8%87%B4%E6%80%A7-%E4%B8%8D%E5%8F%AF%E9%87%8D%E5%A4%8D%E8%AF%BB.png",alt:"img"}})]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("幻读")])])]),t._v(" "),a("p",[t._v("T"),a("sub",[t._v("1")]),t._v(" 读取某个范围的数据,T"),a("sub",[t._v("2")]),t._v(" 在这个范围内插入新的数据,T"),a("sub",[t._v("1")]),t._v(" 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。")]),t._v(" "),a("p",[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/RDB/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%B9%B6%E5%8F%91%E4%B8%80%E8%87%B4%E6%80%A7-%E5%B9%BB%E8%AF%BB.png",alt:"img"}})]),t._v(" "),a("p",[t._v("并发一致性解决方案:")]),t._v(" "),a("p",[t._v("产生并发不一致性问题主要原因是破坏了事务的隔离性,解决方法是通过并发控制来保证隔离性。")]),t._v(" "),a("p",[t._v("并发控制可以通过封锁来实现,但是封锁操作需要用户自己控制,相当复杂。数据库管理系统提供了事务的隔离级别,让用户以一种更轻松的方式处理并发一致性问题。")]),t._v(" "),a("h3",{attrs:{id:"事务隔离"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#事务隔离"}},[t._v("#")]),t._v(" 事务隔离")]),t._v(" "),a("p",[t._v("数据库隔离级别:")]),t._v(" "),a("ul",[a("li",[a("strong",[a("code",[t._v("未提交读(READ UNCOMMITTED)")])]),t._v(" - 事务中的修改,即使没有提交,对其它事务也是可见的。")]),t._v(" "),a("li",[a("strong",[a("code",[t._v("提交读(READ COMMITTED)")])]),t._v(" - 一个事务只能读取已经提交的事务所做的修改。换句话说,一个事务所做的修改在提交之前对其它事务是不可见的。")]),t._v(" "),a("li",[a("strong",[a("code",[t._v("重复读(REPEATABLE READ)")])]),t._v(" - 保证在同一个事务中多次读取同样数据的结果是一样的。")]),t._v(" "),a("li",[a("strong",[a("code",[t._v("串行化(SERIALIXABLE)")])]),t._v(" - 强制事务串行执行。")])]),t._v(" "),a("p",[t._v("数据库隔离级别解决的问题:")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",{staticStyle:{"text-align":"center"}},[t._v("隔离级别")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("脏读")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("不可重复读")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("幻读")])])]),t._v(" "),a("tbody",[a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("未提交读")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("❌")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("❌")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("❌")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("提交读")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("✔️")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("❌")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("❌")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("可重复读")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("✔️")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("✔️")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("❌")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("可串行化")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("✔️")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("✔️")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("✔️")])])])]),t._v(" "),a("h3",{attrs:{id:"分布式事务"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#分布式事务"}},[t._v("#")]),t._v(" 分布式事务")]),t._v(" "),a("p",[t._v("在单一数据节点中,事务仅限于对单一数据库资源的访问控制,称之为 "),a("strong",[t._v("本地事务")]),t._v("。几乎所有的成熟的关系型数据库都提供了对本地事务的原生支持。")]),t._v(" "),a("p",[a("strong",[t._v("分布式事务")]),t._v(" 是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。")]),t._v(" "),a("h4",{attrs:{id:"两阶段提交"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#两阶段提交"}},[t._v("#")]),t._v(" 两阶段提交")]),t._v(" "),a("p",[t._v("两阶段提交(XA)对业务侵入很小。 它最大的优势就是对使用方透明,用户可以像使用本地事务一样使用基于 XA 协议的分布式事务。 XA 协议能够严格保障事务 "),a("code",[t._v("ACID")]),t._v(" 特性。")]),t._v(" "),a("p",[t._v("严格保障事务 "),a("code",[t._v("ACID")]),t._v(" 特性是一把双刃剑。 事务执行在过程中需要将所需资源全部锁定,它更加适用于执行时间确定的短事务。 对于长事务来说,整个事务进行期间对数据的独占,将导致对热点数据依赖的业务系统并发性能衰退明显。 因此,在高并发的性能至上场景中,基于 XA 协议的分布式事务并不是最佳选择。")]),t._v(" "),a("h4",{attrs:{id:"柔性事务"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#柔性事务"}},[t._v("#")]),t._v(" 柔性事务")]),t._v(" "),a("p",[t._v("如果将实现了"),a("code",[t._v("ACID")]),t._v(" 的事务要素的事务称为刚性事务的话,那么基于"),a("code",[t._v("BASE")]),t._v("事务要素的事务则称为柔性事务。 "),a("code",[t._v("BASE")]),t._v("是基本可用、柔性状态和最终一致性这三个要素的缩写。")]),t._v(" "),a("ul",[a("li",[t._v("基本可用(Basically Available)保证分布式事务参与方不一定同时在线。")]),t._v(" "),a("li",[t._v("柔性状态(Soft state)则允许系统状态更新有一定的延时,这个延时对客户来说不一定能够察觉。")]),t._v(" "),a("li",[t._v("而最终一致性(Eventually consistent)通常是通过消息传递的方式保证系统的最终一致性。")])]),t._v(" "),a("p",[t._v("在"),a("code",[t._v("ACID")]),t._v("事务中对隔离性的要求很高,在事务执行过程中,必须将所有的资源锁定。 柔性事务的理念则是通过业务逻辑将互斥锁操作从资源层面上移至业务层面。通过放宽对强一致性要求,来换取系统吞吐量的提升。")]),t._v(" "),a("p",[t._v("基于"),a("code",[t._v("ACID")]),t._v("的强一致性事务和基于"),a("code",[t._v("BASE")]),t._v("的最终一致性事务都不是银弹,只有在最适合的场景中才能发挥它们的最大长处。 可通过下表详细对比它们之间的区别,以帮助开发者进行技术选型。")]),t._v(" "),a("h4",{attrs:{id:"事务方案对比"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#事务方案对比"}},[t._v("#")]),t._v(" 事务方案对比")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",{staticStyle:{"text-align":"left"}}),t._v(" "),a("th",{staticStyle:{"text-align":"left"}},[t._v("本地事务")]),t._v(" "),a("th",{staticStyle:{"text-align":"left"}},[t._v("两(三)阶段事务")]),t._v(" "),a("th",[t._v("柔性事务")])])]),t._v(" "),a("tbody",[a("tr",[a("td",{staticStyle:{"text-align":"left"}},[t._v("业务改造")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("无")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("无")]),t._v(" "),a("td",[t._v("实现相关接口")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"left"}},[t._v("一致性")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("不支持")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("支持")]),t._v(" "),a("td",[t._v("最终一致")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"left"}},[t._v("隔离性")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("不支持")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("支持")]),t._v(" "),a("td",[t._v("业务方保证")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"left"}},[t._v("并发性能")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("无影响")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("严重衰退")]),t._v(" "),a("td",[t._v("略微衰退")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"left"}},[t._v("适合场景")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("业务方处理不一致")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("短事务 & 低并发")]),t._v(" "),a("td",[t._v("长事务 & 高并发")])])])]),t._v(" "),a("h2",{attrs:{id:"分库分表"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#分库分表"}},[t._v("#")]),t._v(" 分库分表")]),t._v(" "),a("h3",{attrs:{id:"什么是分库分表"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#什么是分库分表"}},[t._v("#")]),t._v(" 什么是分库分表")]),t._v(" "),a("blockquote",[a("p",[t._v("什么是分库分表?什么是垂直拆分?什么是水平拆分?什么是 Sharding?")]),t._v(" "),a("p",[t._v("分库分表是为了解决什么问题?")]),t._v(" "),a("p",[t._v("分库分表有什么优点?")]),t._v(" "),a("p",[t._v("分库分表有什么策略?")])]),t._v(" "),a("p",[t._v("分库分表的基本思想就是:把原本完整的数据切分成多个部分,放到不同的数据库或表上。")]),t._v(" "),a("p",[t._v("分库分表一定是为了支撑 "),a("strong",[t._v("高并发、数据量大")]),t._v("两个问题的。")]),t._v(" "),a("h4",{attrs:{id:"垂直切分"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#垂直切分"}},[t._v("#")]),t._v(" 垂直切分")]),t._v(" "),a("blockquote",[a("p",[a("strong",[t._v("垂直切分")]),t._v(",是 "),a("strong",[t._v("把一个有很多字段的表给拆分成多个表,或者是多个库上去")]),t._v("。一般来说,会 "),a("strong",[t._v("将较少的、访问频率较高的字段放到一个表里去")]),t._v(",然后 "),a("strong",[t._v("将较多的、访问频率较低的字段放到另外一个表里去")]),t._v("。因为数据库是有缓存的,访问频率高的行字段越少,就可以在缓存里缓存更多的行,性能就越好。这个一般在表层面做的较多一些。")])]),t._v(" "),a("p",[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/snap/image-20200114211639899.png",alt:"image-20200114211639899"}})]),t._v(" "),a("p",[t._v("一般来说,满足下面的条件就可以考虑扩容了:")]),t._v(" "),a("ul",[a("li",[t._v("Mysql 单库超过 5000 万条记录,Oracle 单库超过 1 亿条记录,DB 压力就很大。")]),t._v(" "),a("li",[t._v("单库超过每秒 2000 个并发时,而一个健康的单库最好保持在每秒 1000 个并发左右,不要太大。")])]),t._v(" "),a("p",[t._v("在数据库的层面使用垂直切分将按数据库中表的密集程度部署到不同的库中,例如将原来的电商数据库垂直切分成商品数据库、用户数据库等。")]),t._v(" "),a("h4",{attrs:{id:"水平拆分"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#水平拆分"}},[t._v("#")]),t._v(" 水平拆分")]),t._v(" "),a("blockquote",[a("p",[a("strong",[t._v("水平拆分")]),t._v(" 又称为 "),a("strong",[t._v("Sharding")]),t._v(",它是将同一个表中的记录拆分到多个结构相同的表中。当 "),a("strong",[t._v("单表数据量太大")]),t._v(" 时,会极大影响 "),a("strong",[t._v("SQL 执行的性能")]),t._v(" 。分表是将原来一张表的数据分布到数据库集群的不同节点上,从而缓解单点的压力。")])]),t._v(" "),a("p",[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/snap/image-20200114211203589.png",alt:"image-20200114211203589"}})]),t._v(" "),a("p",[t._v("一般来说,"),a("strong",[t._v("单表有 200 万条数据")]),t._v(" 的时候,性能就会相对差一些了,需要考虑分表了。但是,这也要视具体情况而定,可能是 100 万条,也可能是 500 万条,SQL 越复杂,就最好让单表行数越少。")]),t._v(" "),a("h4",{attrs:{id:"分库分表的优点"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#分库分表的优点"}},[t._v("#")]),t._v(" 分库分表的优点")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("#")]),t._v(" "),a("th",[t._v("分库分表前")]),t._v(" "),a("th",[t._v("分库分表后")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[t._v("并发支撑情况")]),t._v(" "),a("td",[t._v("单机部署,扛不住高并发")]),t._v(" "),a("td",[t._v("从单机到多机,能承受的并发增加了多倍")])]),t._v(" "),a("tr",[a("td",[t._v("磁盘使用情况")]),t._v(" "),a("td",[t._v("单机磁盘容量几乎撑满")]),t._v(" "),a("td",[t._v("拆分为多个库,数据库服务器磁盘使用率大大降低")])]),t._v(" "),a("tr",[a("td",[t._v("SQL 执行性能")]),t._v(" "),a("td",[t._v("单表数据量太大,SQL 越跑越慢")]),t._v(" "),a("td",[t._v("单表数据量减少,SQL 执行效率明显提升")])])])]),t._v(" "),a("h4",{attrs:{id:"分库分表策略"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#分库分表策略"}},[t._v("#")]),t._v(" 分库分表策略")]),t._v(" "),a("ul",[a("li",[t._v("哈希取模:"),a("code",[t._v("hash(key) % N")]),t._v(" 或 "),a("code",[t._v("id % N")]),t._v(" "),a("ul",[a("li",[t._v("优点:可以平均分配每个库的数据量和请求压力(负载均衡)。")]),t._v(" "),a("li",[t._v("缺点:扩容麻烦,需要数据迁移。")])])]),t._v(" "),a("li",[t._v("范围:可以按照 ID 或时间划分范围。\n"),a("ul",[a("li",[t._v("优点:扩容简单。")]),t._v(" "),a("li",[t._v("缺点:这种策略容易产生热点问题。")])])]),t._v(" "),a("li",[t._v("映射表:使用单独的一个数据库来存储映射关系。\n"),a("ul",[a("li",[t._v("缺点:存储映射关系的数据库也可能成为性能瓶颈,且一旦宕机,分库分表的数据库就无法工作。所以不建议使用这种策略。")]),t._v(" "),a("li",[t._v("优点:扩容简单,可以解决分布式 ID 问题。")])])])]),t._v(" "),a("h3",{attrs:{id:"分库分表中间件"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#分库分表中间件"}},[t._v("#")]),t._v(" 分库分表中间件")]),t._v(" "),a("blockquote",[a("p",[t._v("❓ 常见问题:")]),t._v(" "),a("ul",[a("li",[a("p",[t._v("你用过哪些分库分表中间件,简单介绍一下?")])]),t._v(" "),a("li",[a("p",[t._v("不同的分库分表中间件各自有什么特性,有什么优缺点?")])]),t._v(" "),a("li",[a("p",[t._v("分库分表中间件技术如何选型?")])])])]),t._v(" "),a("h4",{attrs:{id:"常见的分库分表中间件"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#常见的分库分表中间件"}},[t._v("#")]),t._v(" 常见的分库分表中间件")]),t._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"https://github.com/alibaba/cobar",target:"_blank",rel:"noopener noreferrer"}},[t._v("Cobar"),a("OutboundLink")],1),t._v(" - 阿里 b2b 团队开发和开源的,属于 proxy 层方案,就是介于应用服务器和数据库服务器之间。应用程序通过 JDBC 驱动访问 cobar 集群,cobar 根据 SQL 和分库规则对 SQL 做分解,然后分发到 MySQL 集群不同的数据库实例上执行。早些年还可以用,但是最近几年都没更新了,基本没啥人用,差不多算是被抛弃的状态吧。而且不支持读写分离、存储过程、跨库 join 和分页等操作。")]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/alibaba/tb_tddl",target:"_blank",rel:"noopener noreferrer"}},[t._v("TDDL"),a("OutboundLink")],1),t._v(" - 淘宝团队开发的,属于 client 层方案。支持基本的 crud 语法和读写分离,但不支持 join、多表查询等语法。目前使用的也不多,因为还依赖淘宝的 diamond 配置管理系统。")]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/Qihoo360/Atlas",target:"_blank",rel:"noopener noreferrer"}},[t._v("Atlas"),a("OutboundLink")],1),t._v(" - 360 开源的,属于 proxy 层方案,以前是有一些公司在用的,但是确实有一个很大的问题就是社区最新的维护都在 5 年前了。所以,现在用的公司基本也很少了。")]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/dangdangdotcom/sharding-jdbc",target:"_blank",rel:"noopener noreferrer"}},[t._v("sharding-jdbc"),a("OutboundLink")],1),t._v(" - 当当开源的,属于 client 层方案。确实之前用的还比较多一些,因为 SQL 语法支持也比较多,没有太多限制,而且目前推出到了 2.0 版本,支持分库分表、读写分离、分布式 id 生成、柔性事务(最大努力送达型事务、TCC 事务)。而且确实之前使用的公司会比较多一些(这个在官网有登记使用的公司,可以看到从 2017 年一直到现在,是有不少公司在用的),目前社区也还一直在开发和维护,还算是比较活跃,个人认为算是一个现在也"),a("strong",[t._v("可以选择的方案")]),t._v("。")]),t._v(" "),a("li",[a("a",{attrs:{href:"http://www.mycat.org.cn/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mycat"),a("OutboundLink")],1),t._v(" - 基于 cobar 改造的,属于 proxy 层方案,支持的功能非常完善,而且目前应该是非常火的而且不断流行的数据库中间件,社区很活跃,也有一些公司开始在用了。但是确实相比于 sharding jdbc 来说,年轻一些,经历的锤炼少一些。")])]),t._v(" "),a("h4",{attrs:{id:"分库分表中间件技术选型"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#分库分表中间件技术选型"}},[t._v("#")]),t._v(" 分库分表中间件技术选型")]),t._v(" "),a("p",[t._v("建议使用的是 sharding-jdbc 和 mycat。")]),t._v(" "),a("ul",[a("li",[a("p",[a("a",{attrs:{href:"https://github.com/dangdangdotcom/sharding-jdbc",target:"_blank",rel:"noopener noreferrer"}},[t._v("sharding-jdbc"),a("OutboundLink")],1),t._v(" 这种 client 层方案的"),a("strong",[t._v("优点在于不用部署,运维成本低,不需要代理层的二次转发请求,性能很高")]),t._v(",但是如果遇到升级啥的需要各个系统都重新升级版本再发布,各个系统都需要"),a("strong",[t._v("耦合")]),t._v(" sharding-jdbc 的依赖。其本质上通过配置多数据源,然后根据设定的分库分表策略,计算路由,将请求发送到计算得到的节点上。")])]),t._v(" "),a("li",[a("p",[a("a",{attrs:{href:"http://www.mycat.org.cn/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mycat"),a("OutboundLink")],1),t._v(" 这种 proxy 层方案的"),a("strong",[t._v("缺点在于需要部署")]),t._v(",自己运维一套中间件,运维成本高,但是"),a("strong",[t._v("好处在于对于各个项目是透明的")]),t._v(",如果遇到升级之类的都是自己中间件那里搞就行了。")])])]),t._v(" "),a("p",[t._v("通常来说,这两个方案其实都可以选用,但是我个人建议中小型公司选用 sharding-jdbc,client 层方案轻便,而且维护成本低,不需要额外增派人手,而且中小型公司系统复杂度会低一些,项目也没那么多;但是中大型公司最好还是选用 mycat 这类 proxy 层方案,因为可能大公司系统和项目非常多,团队很大,人员充足,那么最好是专门弄个人来研究和维护 mycat,然后大量项目直接透明使用即可。")]),t._v(" "),a("h3",{attrs:{id:"分库分表的问题"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#分库分表的问题"}},[t._v("#")]),t._v(" 分库分表的问题")]),t._v(" "),a("blockquote",[a("ul",[a("li",[a("p",[t._v("分库分表的常见问题有哪些?")])]),t._v(" "),a("li",[a("p",[t._v("你是如何解决分库分表的问题的?")])])]),t._v(" "),a("p",[t._v("下文一一讲解常见分库分表的问题及解决方案。")])]),t._v(" "),a("h4",{attrs:{id:"分布式事务-2"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#分布式事务-2"}},[t._v("#")]),t._v(" 分布式事务")]),t._v(" "),a("p",[t._v("方案一:使用数据库事务")]),t._v(" "),a("ul",[a("li",[t._v("优点:交由数据库管理,简单有效")]),t._v(" "),a("li",[t._v("缺点:性能代价高,特别是 shard 越来越多时")])]),t._v(" "),a("p",[t._v("方案二:由应用程序和数据库共同控制")]),t._v(" "),a("ul",[a("li",[t._v("原理:将一个跨多个数据库的分布式事务分拆成多个仅处于单个数据库上面的小事务,并通过应用程序来总控各个小事务。")]),t._v(" "),a("li",[t._v("优点:性能上有优势")]),t._v(" "),a("li",[t._v("缺点:需要应用程序在事务控制上做灵活设计。如果使用了 spring 的事务管理,改动起来会面临一定的困难。")])]),t._v(" "),a("h4",{attrs:{id:"跨节点-join"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#跨节点-join"}},[t._v("#")]),t._v(" 跨节点 Join")]),t._v(" "),a("p",[t._v("只要是进行切分,跨节点 Join 的问题是不可避免的。但是良好的设计和切分却可以减少此类情况的发生。解决这一问题的普遍做法是分两次查询实现。在第一次查询的结果集中找出关联数据的 id,根据这些 id 发起第二次请求得到关联数据。")]),t._v(" "),a("h4",{attrs:{id:"跨节点的-count-order-by-group-by-以及聚合函数"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#跨节点的-count-order-by-group-by-以及聚合函数"}},[t._v("#")]),t._v(" 跨节点的 count,order by,group by 以及聚合函数")]),t._v(" "),a("p",[t._v("这些是一类问题,因为它们都需要基于全部数据集合进行计算。多数的代理都不会自动处理合并工作。")]),t._v(" "),a("p",[t._v("解决方案:与解决跨节点 join 问题的类似,分别在各个节点上得到结果后在应用程序端进行合并。和 join 不同的是每个节点的查询可以并行执行,因此很多时候它的速度要比单一大表快很多。但如果结果集很大,对应用程序内存的消耗是一个问题。")]),t._v(" "),a("p",[t._v("业务角度上的解决方案:")]),t._v(" "),a("ul",[a("li",[t._v("如果是在前台应用提供分页,则限定用户只能看前面 n 页,这个限制在业务上也是合理的,一般看后面的分页意义不大(如果一定要看,可以要求用户缩小范围重新查询)。")]),t._v(" "),a("li",[t._v("如果是后台批处理任务要求分批获取数据,则可以加大 page size,比如每次获取 5000 条记录,有效减少分页数(当然离线访问一般走备库,避免冲击主库)。")]),t._v(" "),a("li",[t._v("分库设计时,一般还有配套大数据平台汇总所有分库的记录,有些分页查询可以考虑走大数据平台。")])]),t._v(" "),a("h4",{attrs:{id:"分布式-id"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#分布式-id"}},[t._v("#")]),t._v(" 分布式 ID")]),t._v(" "),a("p",[t._v("一旦数据库被切分到多个物理节点上,我们将不能再依赖数据库自身的主键生成机制。一方面,某个分区数据库自生成的 ID 无法保证在全局上是唯一的;另一方面,应用程序在插入数据之前需要先获得 ID,以便进行 SQL 路由。")]),t._v(" "),a("p",[t._v("一些常见的主键生成策略:")]),t._v(" "),a("ul",[a("li",[t._v("使用全局唯一 ID:GUID。")]),t._v(" "),a("li",[t._v("为每个分片指定一个 ID 范围。")]),t._v(" "),a("li",[t._v("分布式 ID 生成器 (如 Twitter 的 Snowflake 算法)。")])]),t._v(" "),a("h4",{attrs:{id:"数据迁移-容量规划-扩容等问题"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#数据迁移-容量规划-扩容等问题"}},[t._v("#")]),t._v(" 数据迁移,容量规划,扩容等问题")]),t._v(" "),a("p",[t._v("来自淘宝综合业务平台团队,它利用对 2 的倍数取余具有向前兼容的特性(如对 4 取余得 1 的数对 2 取余也是 1)来分配数据,避免了行级别的数据迁移,但是依然需要进行表级别的迁移,同时对扩容规模和分表数量都有限制。总得来说,这些方案都不是十分的理想,多多少少都存在一些缺点,这也从一个侧面反映出了 Sharding 扩容的难度。")]),t._v(" "),a("h2",{attrs:{id:"集群"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#集群"}},[t._v("#")]),t._v(" 集群")]),t._v(" "),a("blockquote",[a("p",[t._v("这个专题需要根据熟悉哪个数据库而定,但是主流、成熟的数据库都会实现一些基本功能,只是实现方式、策略上有所差异。由于本人较为熟悉 Mysql,所以下面主要介绍 Mysql 系统架构问题。")])]),t._v(" "),a("h3",{attrs:{id:"复制机制"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#复制机制"}},[t._v("#")]),t._v(" 复制机制")]),t._v(" "),a("p",[t._v("Mysql 支持两种复制:基于行的复制和基于语句的复制。")]),t._v(" "),a("p",[t._v("这两种方式都是在主库上记录二进制日志(binlog),然后在从库上以异步方式更新主库上的日志记录。这意味着:复制过程存在时延,这段时间内,主从数据可能不一致(即最终一致性)。")]),t._v(" "),a("p",[t._v("主要涉及三个线程:binlog 线程、I/O 线程和 SQL 线程。")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("binlog 线程")]),t._v(" :负责将主服务器上的数据更改写入二进制文件(binlog)中。")]),t._v(" "),a("li",[a("strong",[t._v("I/O 线程")]),t._v(" :负责从主服务器上读取二进制日志文件,并写入从服务器的日志中。")]),t._v(" "),a("li",[a("strong",[t._v("SQL 线程")]),t._v(" :负责读取日志并执行 SQL 语句以更新数据。")])]),t._v(" "),a("p",[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/mysql/master-slave.png",alt:"img"}})]),t._v(" "),a("h3",{attrs:{id:"读写分离"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#读写分离"}},[t._v("#")]),t._v(" 读写分离")]),t._v(" "),a("p",[t._v("主服务器用来处理写操作以及实时性要求比较高的读操作,而从服务器用来处理读操作。")]),t._v(" "),a("p",[t._v("读写分离常用代理方式来实现,代理服务器接收应用层传来的读写请求,然后决定转发到哪个服务器。")]),t._v(" "),a("p",[t._v("MySQL 读写分离能提高性能的原因在于:")]),t._v(" "),a("ul",[a("li",[t._v("主从服务器负责各自的读和写,极大程度缓解了锁的争用;")]),t._v(" "),a("li",[t._v("从服务器可以配置 "),a("code",[t._v("MyISAM")]),t._v(" 引擎,提升查询性能以及节约系统开销;")]),t._v(" "),a("li",[t._v("增加冗余,提高可用性。")])]),t._v(" "),a("p",[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/mysql/master-slave-proxy.png",alt:"img"}})]),t._v(" "),a("h2",{attrs:{id:"数据库优化"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#数据库优化"}},[t._v("#")]),t._v(" 数据库优化")]),t._v(" "),a("p",[t._v("数据库优化的路线一般为:SQL 优化、结构优化、配置优化、硬件优化。前两个方向一般是普通开发的考量点,而后两个方向一般是 DBA 的考量点。")]),t._v(" "),a("h3",{attrs:{id:"sql-优化"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#sql-优化"}},[t._v("#")]),t._v(" SQL 优化")]),t._v(" "),a("blockquote",[a("p",[t._v("SQL 优化是数据库优化的最常见、最初级手段。")]),t._v(" "),a("p",[t._v("在执行 SQL 语句,语句中字段的顺序、查询策略等都可能会影响到 SQL 的执行性能。")])]),t._v(" "),a("h4",{attrs:{id:"执行计划"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#执行计划"}},[t._v("#")]),t._v(" 执行计划")]),t._v(" "),a("p",[t._v("如何检验修改后的 SQL 确实有优化效果?这就需要用到执行计划("),a("code",[t._v("EXPLAIN")]),t._v(")。")]),t._v(" "),a("p",[t._v("使用执行计划 "),a("code",[t._v("EXPLAIN")]),t._v(" 用来分析 "),a("code",[t._v("SELECT")]),t._v(" 查询效率,开发人员可以通过分析 "),a("code",[t._v("EXPLAIN")]),t._v(" 结果来优化查询语句。")]),t._v(" "),a("p",[t._v("比较重要的字段有:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("select_type")]),t._v(" - 查询类型,有简单查询、联合查询、子查询等")]),t._v(" "),a("li",[a("code",[t._v("key")]),t._v(" - 使用的索引")]),t._v(" "),a("li",[a("code",[t._v("rows")]),t._v(" - 扫描的行数")])]),t._v(" "),a("blockquote",[a("p",[t._v("更多内容请参考:"),a("a",{attrs:{href:"https://segmentfault.com/a/1190000008131735",target:"_blank",rel:"noopener noreferrer"}},[t._v("MySQL 性能优化神器 Explain 使用分析"),a("OutboundLink")],1)])]),t._v(" "),a("h4",{attrs:{id:"访问数据优化"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#访问数据优化"}},[t._v("#")]),t._v(" 访问数据优化")]),t._v(" "),a("p",[t._v("减少请求的数据量:")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("只返回必要的列")]),t._v(" - 不要查询不需要的列,尽量避免使用 "),a("code",[t._v("SELECT *")]),t._v(" 语句。")]),t._v(" "),a("li",[a("strong",[t._v("只返回必要的行")]),t._v(" - 使用 "),a("code",[t._v("WHERE")]),t._v(" 语句进行查询过滤,有时候也需要使用 "),a("code",[t._v("LIMIT")]),t._v(" 语句来限制返回的数据。")]),t._v(" "),a("li",[a("strong",[t._v("缓存重复查询的数据")]),t._v(" - 使用缓存可以避免在数据库中进行查询,特别要查询的数据经常被重复查询,缓存可以带来的查询性能提升将会是非常明显的。")])]),t._v(" "),a("p",[t._v("减少服务器端扫描的行数:")]),t._v(" "),a("ul",[a("li",[t._v("最有效的方式是"),a("strong",[t._v("使用索引来覆盖查询")]),t._v("(即 "),a("code",[t._v("WHERE")]),t._v(" 后的过滤查询字段最好是索引字段)。")])]),t._v(" "),a("h4",{attrs:{id:"重构查询方式"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#重构查询方式"}},[t._v("#")]),t._v(" 重构查询方式")]),t._v(" "),a("h5",{attrs:{id:"切分查询"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#切分查询"}},[t._v("#")]),t._v(" 切分查询")]),t._v(" "),a("p",[t._v("一个大查询如果一次性执行的话,可能一次锁住很多数据、占满整个事务日志、耗尽系统资源、阻塞很多小的但重要的查询。")]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[t._v("DELEFT "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" messages "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("create")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" DATE_SUB"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("NOW")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INTERVAL")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("MONTH")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[t._v("rows_affected "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("do")]),t._v(" {\n rows_affected "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" do_query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"DELETE FROM messages WHERE create < DATE_SUB(NOW(), INTERVAL 3 MONTH) LIMIT 10000"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n} "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("while")]),t._v(" rows_affected "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n")])])]),a("h5",{attrs:{id:"分解关联查询"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#分解关联查询"}},[t._v("#")]),t._v(" 分解关联查询")]),t._v(" "),a("p",[t._v("将一个大连接查询(JOIN)分解成对每一个表进行一次单表查询,然后将结果在应用程序中进行关联,这样做的好处有:")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("缓存更高效")]),t._v("。对于连接查询,如果其中一个表发生变化,那么整个查询缓存就无法使用。而分解后的多个查询,即使其中一个表发生变化,对其它表的查询缓存依然可以使用。")]),t._v(" "),a("li",[t._v("分解成多个单表查询,这些单表查询的缓存结果更可能被其它查询使用到,从而"),a("strong",[t._v("减少冗余记录的查询")]),t._v("。")]),t._v(" "),a("li",[a("strong",[t._v("减少锁竞争")]),t._v(";")]),t._v(" "),a("li",[a("strong",[t._v("在应用层进行连接,可以更容易对数据库进行拆分")]),t._v(",从而更容易做到高性能和可扩展。")]),t._v(" "),a("li",[a("strong",[t._v("查询本身效率也可能会有所提升")]),t._v("。例如下面的例子中,使用 "),a("code",[t._v("IN()")]),t._v(" 代替连接查询,可以让 MySQL 按照 ID 顺序进行查询,这可能比随机的连接要更高效。")])]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" tag\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("JOIN")]),t._v(" tag_post "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ON")]),t._v(" tag_post"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tag_id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("tag"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("JOIN")]),t._v(" post "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ON")]),t._v(" tag_post"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("post_id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("post"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" tag"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tag"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'mysql'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" tag "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" tag"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'mysql'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" tag_post "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" tag_id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1234")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" post "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" post"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("IN")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("123")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("456")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("567")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("9098")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8904")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("h4",{attrs:{id:"sql-语句细节"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#sql-语句细节"}},[t._v("#")]),t._v(" SQL 语句细节")]),t._v(" "),a("h5",{attrs:{id:"选择最有效率的表名顺序"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#选择最有效率的表名顺序"}},[t._v("#")]),t._v(" 选择最有效率的表名顺序")]),t._v(" "),a("p",[t._v("数据库按照"),a("strong",[t._v("从右到左的顺序处理 FROM 子句中的表名,FROM 子句中写在最后的表将被最先处理")]),t._v("。")]),t._v(" "),a("p",[t._v("在 "),a("code",[t._v("FROM")]),t._v(" 子句中包含多个表的情况下:")]),t._v(" "),a("ul",[a("li",[t._v("如果多个表是完全"),a("strong",[t._v("无关系")]),t._v("的话,将记录和列名最少的表,写在最后,然后依次类推。也就是说:"),a("strong",[t._v("选择记录条数最少的表放在最后")]),t._v("。")])]),t._v(" "),a("p",[t._v("如果有 3 个以上的表连接查询:")]),t._v(" "),a("ul",[a("li",[t._v("如果多个表是"),a("strong",[t._v("有关系")]),t._v("的话,将引用最多的表,放在最后,然后依次类推。也就是说:"),a("strong",[t._v("被其他表所引用的表放在最后")]),t._v("。")])]),t._v(" "),a("p",[t._v("例如:查询员工的编号,姓名,工资,工资等级,部门名")]),t._v(" "),a("p",[a("strong",[t._v("emp 表被引用得最多,记录数也是最多,因此放在 form 字句的最后面")])]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" emp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("empno"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("emp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ename"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("emp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("salgrade"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("grade"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("dept"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("dname\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" salgrade"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("dept"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("emp\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("emp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("deptno "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" dept"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("deptno"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("and")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("emp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sal "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("between")]),t._v(" salgrade"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("losal "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("and")]),t._v(" salgrade"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("hisal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h5",{attrs:{id:"where-子句中的连接顺序"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#where-子句中的连接顺序"}},[t._v("#")]),t._v(" WHERE 子句中的连接顺序")]),t._v(" "),a("p",[t._v("数据库按照"),a("strong",[t._v("从右到左的顺序解析 "),a("code",[t._v("WHERE")]),t._v(" 子句")]),t._v("。")]),t._v(" "),a("p",[t._v("因此,"),a("strong",[t._v("表之间的连接必须写在其他 WHERE 条件的左边")]),t._v(",那些"),a("strong",[t._v("可以过滤掉最大数量记录的条件必须写在 WHERE 子句的之右")]),t._v("。")]),t._v(" "),a("p",[a("strong",[t._v("emp.sal 可以过滤多条记录,写在 WHERE 字句的最右边")])]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" emp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("empno"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("emp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ename"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("emp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("dept"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("dname\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" dept"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("emp\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("emp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("deptno "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" dept"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("deptno"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("and")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("emp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sal "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1500")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h5",{attrs:{id:"select-子句中避免使用-号"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#select-子句中避免使用-号"}},[t._v("#")]),t._v(" SELECT 子句中避免使用 "),a("code",[t._v("*")]),t._v(" 号")]),t._v(" "),a("p",[t._v("我们当时学习的时候,“*” 号是可以获取表中全部的字段数据的。")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("但是它要通过查询数据字典完成的,这意味着将耗费更多的时间")])]),t._v(" "),a("li",[t._v("使用*号写出来的 SQL 语句也不够直观。")])]),t._v(" "),a("hr"),t._v(" "),a("h5",{attrs:{id:"用-truncate-替代-delete"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#用-truncate-替代-delete"}},[t._v("#")]),t._v(" 用 TRUNCATE 替代 DELETE")]),t._v(" "),a("p",[t._v("如果需要"),a("strong",[t._v("清空所有表记录")]),t._v(",使用 TRUNCATE 比 DELETE 执行效率高:")]),t._v(" "),a("p",[a("strong",[t._v("DELETE 是一条一条记录的删除,而 Truncate 是将整个表删除,仅保留表结构")])]),t._v(" "),a("h5",{attrs:{id:"使用内部函数提高-sql-效率"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#使用内部函数提高-sql-效率"}},[t._v("#")]),t._v(" 使用内部函数提高 SQL 效率")]),t._v(" "),a("p",[a("strong",[t._v("例如使用 mysql 的 concat() 函数会比使用 "),a("code",[t._v("||")]),t._v(" 拼接速度快,因为 concat() 函数已经被 mysql 优化过了。")])]),t._v(" "),a("h5",{attrs:{id:"使用表或列的别名"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#使用表或列的别名"}},[t._v("#")]),t._v(" 使用表或列的别名")]),t._v(" "),a("p",[t._v("如果表或列的名称太长了,使用一些简短的别名也能稍微提高一些 SQL 的性能。毕竟要扫描的字符长度就变少了。")]),t._v(" "),a("h5",{attrs:{id:"sql-关键字大写"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#sql-关键字大写"}},[t._v("#")]),t._v(" SQL 关键字大写")]),t._v(" "),a("p",[t._v("我们在编写 SQL 的时候,官方推荐的是使用大写来写关键字,"),a("strong",[t._v("因为 Oracle 服务器总是先将小写字母转成大写后,才执行")])]),t._v(" "),a("h5",{attrs:{id:"用-替代"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#用-替代"}},[t._v("#")]),t._v(" 用 "),a("code",[t._v(">=")]),t._v(" 替代 "),a("code",[t._v(">")])]),t._v(" "),a("p",[t._v("❌ 低效方式:")]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- 首先定位到DEPTNO=3的记录并且扫描到第一个DEPT大于3的记录")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" EMP "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" DEPTNO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v("\n")])])]),a("p",[t._v("✔ 高效方式:")]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- 直接跳到第一个DEPT等于4的记录")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" EMP "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" DEPTNO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),t._v("\n")])])]),a("h5",{attrs:{id:"用-in-替代-or"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#用-in-替代-or"}},[t._v("#")]),t._v(" 用 IN 替代 OR")]),t._v(" "),a("p",[t._v("❌ 低效方式:")]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" emp "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v(" sal "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1500")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("or")]),t._v(" sal "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3000")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("or")]),t._v(" sal "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("800")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("✔ 高效方式:")]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" emp "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v(" sal "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("in")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1500")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3000")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("800")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("h5",{attrs:{id:"总是使用索引的第一个列"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#总是使用索引的第一个列"}},[t._v("#")]),t._v(" 总是使用索引的第一个列")]),t._v(" "),a("p",[t._v("如果索引是建立在多个列上,只有在它的第一个列被 WHERE 子句引用时,优化器才会选择使用该索引。 当只引用索引的第二个列时,不引用索引的第一个列时,优化器使用了全表扫描而忽略了索引")]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("create")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("index")]),t._v(" emp_sal_job_idex\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" emp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("job"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("----------------------------------")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" emp\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v(" job "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'SALES'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("h5",{attrs:{id:"sql-关键字尽量大写"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#sql-关键字尽量大写"}},[t._v("#")]),t._v(" SQL 关键字尽量大写")]),t._v(" "),a("p",[t._v("SQL 关键字尽量大写,如:Oracle 默认会将 SQL 语句中的关键字转为大写后在执行。")]),t._v(" "),a("h3",{attrs:{id:"结构优化"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#结构优化"}},[t._v("#")]),t._v(" 结构优化")]),t._v(" "),a("p",[t._v("数据库结构优化可以从以下方向着手:")]),t._v(" "),a("ul",[a("li",[t._v("数据类型优化")]),t._v(" "),a("li",[t._v("范式和反范式优化")]),t._v(" "),a("li",[t._v("索引优化 - 细节请看索引和约束章节")]),t._v(" "),a("li",[t._v("分库分表 - 细节请看分库分表章节")])]),t._v(" "),a("h4",{attrs:{id:"数据类型优化原则"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#数据类型优化原则"}},[t._v("#")]),t._v(" 数据类型优化原则")]),t._v(" "),a("ul",[a("li",[t._v("更小的通常更好")]),t._v(" "),a("li",[t._v("简单就好,如整型比字符型操作代价低")]),t._v(" "),a("li",[t._v("尽量避免 NULL")])]),t._v(" "),a("h4",{attrs:{id:"范式和反范式"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#范式和反范式"}},[t._v("#")]),t._v(" 范式和反范式")]),t._v(" "),a("p",[t._v("范式和反范式各有利弊,需要根据实际情况权衡。")]),t._v(" "),a("p",[t._v("范式化的目标是"),a("strong",[t._v("尽力减少冗余列,节省空间")]),t._v("。")]),t._v(" "),a("ul",[a("li",[a("p",[t._v("范式化的优点是:")]),t._v(" "),a("ul",[a("li",[t._v("减少冗余列,要写的数据就少,写操作的性能提高;")]),t._v(" "),a("li",[t._v("检索列数据时,"),a("code",[t._v("DISTINCT")]),t._v(" 或 "),a("code",[t._v("GROUP BY")]),t._v(" 操作减少。")])])]),t._v(" "),a("li",[a("p",[t._v("范式化的缺点是:增加关联查询。")])])]),t._v(" "),a("p",[t._v("反范式化的目标是"),a("strong",[t._v("适当增加冗余列,以避免关联查询")]),t._v("。")]),t._v(" "),a("p",[t._v("反范式化的缺点是:")]),t._v(" "),a("ul",[a("li",[t._v("冗余列增多,空间变大,写操作性能下降;")]),t._v(" "),a("li",[t._v("检索列数据时,DISTINCT 或 GROUP BY 操作变多;")])]),t._v(" "),a("h3",{attrs:{id:"配置优化"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#配置优化"}},[t._v("#")]),t._v(" 配置优化")]),t._v(" "),a("blockquote",[a("p",[t._v("配置优化主要是针对 Mysql 服务器,例如:"),a("code",[t._v("max_connections")]),t._v("、"),a("code",[t._v("max_heap_table_size")]),t._v("、"),a("code",[t._v("open_files_limit")]),t._v("、"),a("code",[t._v("max_allowed_packet")]),t._v(" 等等。")]),t._v(" "),a("p",[t._v("在不同环境,不同场景下,应该酌情使用合理的配置。这种优化比较考验 Mysql 运维经验,一般是 DBA 的考量,普通开发接触的较少。")]),t._v(" "),a("p",[t._v("Mysql 配置说明请参考:"),a("RouterLink",{attrs:{to:"/12.数据库/03.关系型数据库/01.综合/sql/mysql/mysql-config.html"}},[t._v("Mysql 服务器配置说明")])],1)]),t._v(" "),a("h3",{attrs:{id:"硬件优化"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#硬件优化"}},[t._v("#")]),t._v(" 硬件优化")]),t._v(" "),a("p",[t._v("数据库扩容、使用高配设备等等。核心就是一个字:钱。")]),t._v(" "),a("h2",{attrs:{id:"数据库理论"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#数据库理论"}},[t._v("#")]),t._v(" 数据库理论")]),t._v(" "),a("h3",{attrs:{id:"函数依赖"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#函数依赖"}},[t._v("#")]),t._v(" 函数依赖")]),t._v(" "),a("p",[t._v("记 A->B 表示 A 函数决定 B,也可以说 B 函数依赖于 A。")]),t._v(" "),a("p",[t._v("如果 {A1,A2,... ,An} 是关系的一个或多个属性的集合,该集合函数决定了关系的其它所有属性并且是最小的,那么该集合就称为键码。")]),t._v(" "),a("p",[t._v("对于 A->B,如果能找到 A 的真子集 A',使得 A'-> B,那么 A->B 就是部分函数依赖,否则就是完全函数依赖;")]),t._v(" "),a("p",[t._v("对于 A->B,B->C,则 A->C 是一个传递依赖。")]),t._v(" "),a("h3",{attrs:{id:"异常"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#异常"}},[t._v("#")]),t._v(" 异常")]),t._v(" "),a("p",[t._v("以下的学生课程关系的函数依赖为 Sno, Cname -> Sname, Sdept, Mname, Grade,键码为 {Sno, Cname}。也就是说,确定学生和课程之后,就能确定其它信息。")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",{staticStyle:{"text-align":"center"}},[t._v("Sno")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Sname")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Sdept")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Mname")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Cname")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Grade")])])]),t._v(" "),a("tbody",[a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学生-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("院长-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("课程-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("90")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学生-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("院长-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("课程-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("80")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学生-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("院长-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("课程-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("100")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("3")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学生-3")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("院长-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("课程-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("95")])])])]),t._v(" "),a("p",[t._v("不符合范式的关系,会产生很多异常,主要有以下四种异常:")]),t._v(" "),a("ul",[a("li",[t._v("冗余数据:例如 学生-2 出现了两次。")]),t._v(" "),a("li",[t._v("修改异常:修改了一个记录中的信息,但是另一个记录中相同的信息却没有被修改。")]),t._v(" "),a("li",[t._v("删除异常:删除一个信息,那么也会丢失其它信息。例如如果删除了 课程-1,需要删除第一行和第三行,那么 学生-1 的信息就会丢失。")]),t._v(" "),a("li",[t._v("插入异常,例如想要插入一个学生的信息,如果这个学生还没选课,那么就无法插入。")])]),t._v(" "),a("h3",{attrs:{id:"范式"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#范式"}},[t._v("#")]),t._v(" 范式")]),t._v(" "),a("p",[t._v("范式理论是为了解决以上提到四种异常。")]),t._v(" "),a("p",[t._v("高级别范式的依赖于低级别的范式,1NF 是最低级别的范式。")]),t._v(" "),a("div",{attrs:{align:"center"}},[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/RDB/数据库范式.png"}})]),t._v(" "),a("h4",{attrs:{id:"第一范式-1nf"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#第一范式-1nf"}},[t._v("#")]),t._v(" 第一范式 (1NF)")]),t._v(" "),a("p",[t._v("属性不可分。")]),t._v(" "),a("h4",{attrs:{id:"第二范式-2nf"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#第二范式-2nf"}},[t._v("#")]),t._v(" 第二范式 (2NF)")]),t._v(" "),a("ul",[a("li",[a("p",[t._v("每个非主属性完全函数依赖于键码。")])]),t._v(" "),a("li",[a("p",[t._v("可以通过分解来满足。")])])]),t._v(" "),a("p",[a("strong",[t._v("分解前")])]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",{staticStyle:{"text-align":"center"}},[t._v("Sno")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Sname")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Sdept")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Mname")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Cname")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Grade")])])]),t._v(" "),a("tbody",[a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学生-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("院长-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("课程-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("90")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学生-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("院长-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("课程-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("80")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学生-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("院长-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("课程-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("100")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("3")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学生-3")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("院长-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("课程-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("95")])])])]),t._v(" "),a("p",[t._v("以上学生课程关系中,{Sno, Cname} 为键码,有如下函数依赖:")]),t._v(" "),a("ul",[a("li",[t._v("Sno -> Sname, Sdept")]),t._v(" "),a("li",[t._v("Sdept -> Mname")]),t._v(" "),a("li",[t._v("Sno, Cname-> Grade")])]),t._v(" "),a("p",[t._v("Grade 完全函数依赖于键码,它没有任何冗余数据,每个学生的每门课都有特定的成绩。")]),t._v(" "),a("p",[t._v("Sname, Sdept 和 Mname 都部分依赖于键码,当一个学生选修了多门课时,这些数据就会出现多次,造成大量冗余数据。")]),t._v(" "),a("p",[a("strong",[t._v("分解后")])]),t._v(" "),a("p",[t._v("关系-1")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",{staticStyle:{"text-align":"center"}},[t._v("Sno")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Sname")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Sdept")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Mname")])])]),t._v(" "),a("tbody",[a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学生-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("院长-1")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学生-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("院长-2")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("3")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学生-3")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("院长-2")])])])]),t._v(" "),a("p",[t._v("有以下函数依赖:")]),t._v(" "),a("ul",[a("li",[t._v("Sno -> Sname, Sdept, Mname")]),t._v(" "),a("li",[t._v("Sdept -> Mname")])]),t._v(" "),a("p",[t._v("关系-2")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",{staticStyle:{"text-align":"center"}},[t._v("Sno")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Cname")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Grade")])])]),t._v(" "),a("tbody",[a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("课程-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("90")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("课程-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("80")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("课程-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("100")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("3")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("课程-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("95")])])])]),t._v(" "),a("p",[t._v("有以下函数依赖:")]),t._v(" "),a("ul",[a("li",[t._v("Sno, Cname -> Grade")])]),t._v(" "),a("h4",{attrs:{id:"第三范式-3nf"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#第三范式-3nf"}},[t._v("#")]),t._v(" 第三范式 (3NF)")]),t._v(" "),a("ul",[a("li",[t._v("非主属性不传递依赖于键码。")])]),t._v(" "),a("p",[t._v("上面的 关系-1 中存在以下传递依赖:Sno -> Sdept -> Mname,可以进行以下分解:")]),t._v(" "),a("p",[t._v("关系-11")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",{staticStyle:{"text-align":"center"}},[t._v("Sno")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Sname")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Sdept")])])]),t._v(" "),a("tbody",[a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学生-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-1")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学生-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-2")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("3")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学生-3")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-2")])])])]),t._v(" "),a("p",[t._v("关系-12")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",{staticStyle:{"text-align":"center"}},[t._v("Sdept")]),t._v(" "),a("th",{staticStyle:{"text-align":"center"}},[t._v("Mname")])])]),t._v(" "),a("tbody",[a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-1")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("院长-1")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("学院-2")]),t._v(" "),a("td",{staticStyle:{"text-align":"center"}},[t._v("院长-2")])])])]),t._v(" "),a("h2",{attrs:{id:"存储引擎"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#存储引擎"}},[t._v("#")]),t._v(" 存储引擎")]),t._v(" "),a("p",[t._v("Mysql 有多种存储引擎,"),a("strong",[t._v("不同的存储引擎保存数据和索引的方式是不同的,但表的定义则是在 Mysql 服务层统一处理的")]),t._v("。")]),t._v(" "),a("p",[t._v("简单列举几个存储引擎:")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("InnoDB")]),t._v(" - Mysql 的默认事务型存储引擎,并提供了行级锁和外键的约束。性能不错且支持自动故障恢复。")]),t._v(" "),a("li",[a("strong",[t._v("MyISAM")]),t._v(" - Mysql 5.1 版本前的默认存储引擎。特性丰富但不支持事务,也不支持行级锁和外键,也没有故障恢复功能。")]),t._v(" "),a("li",[a("strong",[t._v("CSV")]),t._v(" - 可以将 CSV 文件作为 Mysql 的表来处理,但这种表不支持索引。")]),t._v(" "),a("li",[a("strong",[t._v("MEMORY")]),t._v(" 。所有的数据都在内存中,数据的处理速度快,但是安全性不高。")])]),t._v(" "),a("h3",{attrs:{id:"innodb-vs-myisam"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#innodb-vs-myisam"}},[t._v("#")]),t._v(" InnoDB vs. MyISAM")]),t._v(" "),a("p",[t._v("InnoDB 和 MyISAM 是目前使用的最多的两种 Mysql 存储引擎。")]),t._v(" "),a("ul",[a("li",[t._v("数据结构比较:\n"),a("ul",[a("li",[t._v("InnoDB 和 MyISAM 的索引数据结构"),a("strong",[t._v("都是 B+ 树")]),t._v("。")]),t._v(" "),a("li",[t._v("MyIASM 的 B+ 树中存储的内容实际上是实际数据的地址值。也就是说它的索引和实际数据是分开的,"),a("strong",[t._v("只不过使用索引指向了实际数据。这种索引的模式被称为非聚集索引。")])]),t._v(" "),a("li",[t._v("InnoDB 的 B+ 树中存储的内容是实际的数据,这种索引有被称为聚集索引。")])])]),t._v(" "),a("li",[t._v("事务支持比较:\n"),a("ul",[a("li",[t._v("InnoDB 支持事务,并提供了行级锁和外键的约束。")]),t._v(" "),a("li",[t._v("MyIASM 不支持事务,也不支持行级锁和外键。")])])]),t._v(" "),a("li",[t._v("故障恢复比较:\n"),a("ul",[a("li",[t._v("InnoDB 支持故障恢复。")]),t._v(" "),a("li",[t._v("MyISAM 不支持故障恢复。")])])])]),t._v(" "),a("h2",{attrs:{id:"数据库比较"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#数据库比较"}},[t._v("#")]),t._v(" 数据库比较")]),t._v(" "),a("h3",{attrs:{id:"常见数据库比较"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#常见数据库比较"}},[t._v("#")]),t._v(" 常见数据库比较")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("Oracle")]),t._v(" - 久负盛名的商业数据库。功能强大、稳定。最大的缺点就是费钱。")]),t._v(" "),a("li",[a("code",[t._v("Mysql")]),t._v(" - 曾经是互联网公司的最爱,但自动 Mysql 被 Oracle 公司收购后,好日子可能一去不复返。很多公司或开源项目已经逐渐寻找其他的开源产品来替代 Mysql。")]),t._v(" "),a("li",[a("code",[t._v("MariaDB")]),t._v(" - 开源关系型数据库。 MySQL 的真正开源的发行版本,由 Mysql 部分核心人员创建。可作为 Mysql 的替代产品。")]),t._v(" "),a("li",[a("code",[t._v("PostgreSQL")]),t._v(" - 开源关系型数据库。和 MySQL 的工作方式非常相似,社区支持做得很好。可作为 Mysql 的替代产品。")]),t._v(" "),a("li",[a("code",[t._v("SQLite")]),t._v(" - 开源的轻量级数据库,移动端常常使用。")]),t._v(" "),a("li",[a("code",[t._v("H2")]),t._v(" - 内存数据库,一般用作开发、测试环境数据库。")]),t._v(" "),a("li",[a("code",[t._v("SQL Server")]),t._v(" - 微软 Windows 生态系统的数据库。我想,Java 程序员应该没人用吧。")])]),t._v(" "),a("h3",{attrs:{id:"oracle-vs-mysql"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#oracle-vs-mysql"}},[t._v("#")]),t._v(" Oracle vs. Mysql")]),t._v(" "),a("p",[t._v("目前为止,Java 领域用的最多的关系型数据库,应该还是 Oracle 和 Mysql,所以这里做一下比较。")]),t._v(" "),a("h4",{attrs:{id:"数据库对象差异"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#数据库对象差异"}},[t._v("#")]),t._v(" 数据库对象差异")]),t._v(" "),a("p",[t._v("在 Mysql 中,"),a("strong",[t._v("一个用户可以创建多个库")]),t._v("。")]),t._v(" "),a("p",[t._v("而在 Oracle 中,Oracle 服务器是由两部分组成")]),t._v(" "),a("ul",[a("li",[t._v("数据库实例【理解为对象,看不见的】")]),t._v(" "),a("li",[t._v("数据库【理解为类,看得见的】")])]),t._v(" "),a("p",[a("strong",[t._v("一个数据库实例可拥有多个用户,一个用户默认拥有一个表空间。")])]),t._v(" "),a("p",[a("strong",[t._v("表空间是存储我们数据库表的地方,表空间内可以有多个文件。")])]),t._v(" "),a("h4",{attrs:{id:"sql-差异"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#sql-差异"}},[t._v("#")]),t._v(" SQL 差异")]),t._v(" "),a("p",[t._v("(1)主键递增")]),t._v(" "),a("p",[t._v("Mysql 可以设置 "),a("code",[t._v("AUTO_INCREMENT")]),t._v(" 约束来指定主键为自增序列。")]),t._v(" "),a("p",[t._v("Oracle 需要通过 "),a("code",[t._v("CREATE SEQUENCE")]),t._v(" 创建序列。")]),t._v(" "),a("p",[t._v("(2)分页查询")]),t._v(" "),a("p",[t._v("Mysql 分页基于 "),a("code",[t._v("SELECT ... FROM ... LIMIT ...")]),t._v(" 完成,较简单。")]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" help_category "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("order")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("by")]),t._v(" parent_category_id "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("limit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("Oracle 分页基于 "),a("code",[t._v("SELECT ... FROM (SELECT ROWNUM ...) WHERE ...")]),t._v(" 完成,较复杂。")]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" rownum rr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" emp "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("order")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("by")]),t._v(" sal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v(" rr"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("and")]),t._v(" rr"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<=")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("h4",{attrs:{id:"事务差异"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#事务差异"}},[t._v("#")]),t._v(" 事务差异")]),t._v(" "),a("ul",[a("li",[t._v("auto commit\n"),a("ul",[a("li",[t._v("Mysql 事务是 autocommit 模式,即自动提交事务;")]),t._v(" "),a("li",[t._v("Oracle 事务需要手动 "),a("code",[t._v("COMMIT")]),t._v("。")])])]),t._v(" "),a("li",[t._v("事务隔离级别\n"),a("ul",[a("li",[t._v("Mysql 默认的事务隔离级别是可重复读("),a("code",[t._v("REPEATABLE READ")]),t._v(")")]),t._v(" "),a("li",[t._v("Oracle 支持读已提交("),a("code",[t._v("READ COMMITTED")]),t._v(")和串行化("),a("code",[t._v("SERIALIZABLE")]),t._v(") 两种事务隔离级别,默认事务隔离级别是读已提交("),a("code",[t._v("READ COMMITTED")]),t._v(")")])])])]),t._v(" "),a("h3",{attrs:{id:"数据类型比较"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#数据类型比较"}},[t._v("#")]),t._v(" 数据类型比较")]),t._v(" "),a("blockquote",[a("p",[t._v("不同数据库中,对数据类型的支持是不一样的。")]),t._v(" "),a("p",[t._v("即使存在同一种数据类型,也可能存在名称不同、或大小不同等问题。")]),t._v(" "),a("p",[t._v("因此,对于数据类型的支持详情必须参考各数据库的官方文档。")])]),t._v(" "),a("p",[t._v("下面列举一些常见数据类型对比:")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",{staticStyle:{"text-align":"left"}},[t._v("数据类型")]),t._v(" "),a("th",{staticStyle:{"text-align":"left"}},[t._v("Oracle")]),t._v(" "),a("th",{staticStyle:{"text-align":"left"}},[t._v("MySQL")]),t._v(" "),a("th",{staticStyle:{"text-align":"left"}},[t._v("PostgreSQL")])])]),t._v(" "),a("tbody",[a("tr",[a("td",{staticStyle:{"text-align":"left"}},[a("code",[t._v("boolean")])]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Byte")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("N/A")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Boolean")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"left"}},[a("code",[t._v("integer")])]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Number")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Int Integer")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Int Integer")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"left"}},[a("code",[t._v("float")])]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Number")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Float")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Numeric")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"left"}},[a("code",[t._v("currency")])]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("N/A")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("N/A")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Money")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"left"}},[a("code",[t._v("string (fixed)")])]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Char")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Char")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Char")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"left"}},[a("code",[t._v("string (variable)")])]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Varchar Varchar2")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Varchar")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Varchar")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"left"}},[a("code",[t._v("binary object")])]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Long Raw")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Blob Text")]),t._v(" "),a("td",{staticStyle:{"text-align":"left"}},[t._v("Binary Varbinary")])])])]),t._v(" "),a("blockquote",[a("p",[t._v("数据类型对比表摘自 "),a("a",{attrs:{href:"https://www.runoob.com/sql/sql-datatypes-general.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("SQL 通用数据类型"),a("OutboundLink")],1),t._v("、"),a("a",{attrs:{href:"https://www.runoob.com/sql/sql-datatypes.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("SQL 用于各种数据库的数据类型"),a("OutboundLink")],1)])]),t._v(" "),a("h2",{attrs:{id:"sql-faq"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#sql-faq"}},[t._v("#")]),t._v(" SQL FAQ")]),t._v(" "),a("h3",{attrs:{id:"select-count-、select-count-1-和-select-count-具体字段-性能有差别吗"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#select-count-、select-count-1-和-select-count-具体字段-性能有差别吗"}},[t._v("#")]),t._v(" SELECT COUNT(*)、SELECT COUNT(1) 和 SELECT COUNT(具体字段) 性能有差别吗?")]),t._v(" "),a("p",[t._v("在 MySQL InnoDB 存储引擎中,"),a("code",[t._v("COUNT(*)")]),t._v(" 和 "),a("code",[t._v("COUNT(1)")]),t._v(" 都是对所有结果进行 "),a("code",[t._v("COUNT")]),t._v("。因此"),a("code",[t._v("COUNT(*)")]),t._v("和"),a("code",[t._v("COUNT(1)")]),t._v("本质上并没有区别,执行的复杂度都是 "),a("code",[t._v("O(N)")]),t._v(",也就是采用全表扫描,进行循环 + 计数的方式进行统计。")]),t._v(" "),a("p",[t._v("如果是 MySQL MyISAM 存储引擎,统计数据表的行数只需要"),a("code",[t._v("O(1)")]),t._v("的复杂度,这是因为每张 MyISAM 的数据表都有一个 meta 信息存储了"),a("code",[t._v("row_count")]),t._v("值,而一致性则由表级锁来保证。因为 InnoDB 支持事务,采用行级锁和 MVCC 机制,所以无法像 MyISAM 一样,只维护一个"),a("code",[t._v("row_count")]),t._v("变量,因此需要采用扫描全表,进行循环 + 计数的方式来完成统计。")]),t._v(" "),a("p",[t._v("需要注意的是,在实际执行中,"),a("code",[t._v("COUNT(*)")]),t._v("和"),a("code",[t._v("COUNT(1)")]),t._v("的执行时间可能略有差别,不过你还是可以把它俩的执行效率看成是相等的。")]),t._v(" "),a("p",[t._v("另外在 InnoDB 引擎中,如果采用"),a("code",[t._v("COUNT(*)")]),t._v("和"),a("code",[t._v("COUNT(1)")]),t._v("来统计数据行数,要尽量采用二级索引。因为主键采用的索引是聚簇索引,聚簇索引包含的信息多,明显会大于二级索引(非聚簇索引)。对于"),a("code",[t._v("COUNT(*)")]),t._v("和"),a("code",[t._v("COUNT(1)")]),t._v("来说,它们不需要查找具体的行,只是统计行数,系统会自动采用占用空间更小的二级索引来进行统计。")]),t._v(" "),a("p",[t._v("然而如果想要查找具体的行,那么采用主键索引的效率更高。如果有多个二级索引,会使用 key_len 小的二级索引进行扫描。当没有二级索引的时候,才会采用主键索引来进行统计。")]),t._v(" "),a("p",[t._v("这里我总结一下:")]),t._v(" "),a("ol",[a("li",[t._v("一般情况下,三者执行的效率为 "),a("code",[t._v("COUNT(*)")]),t._v("= "),a("code",[t._v("COUNT(1)")]),t._v("> "),a("code",[t._v("COUNT(字段)")]),t._v("。我们尽量使用"),a("code",[t._v("COUNT(*)")]),t._v(",当然如果你要统计的是某个字段的非空数据行数,则另当别论,毕竟比较执行效率的前提是结果一样才可以。")]),t._v(" "),a("li",[t._v("如果要统计"),a("code",[t._v("COUNT(*)")]),t._v(",尽量在数据表上建立二级索引,系统会自动采用"),a("code",[t._v("key_len")]),t._v("小的二级索引进行扫描,这样当我们使用"),a("code",[t._v("SELECT COUNT(*)")]),t._v("的时候效率就会提升,有时候可以提升几倍甚至更高。")])]),t._v(" "),a("blockquote",[a("p",[t._v("——摘自"),a("a",{attrs:{href:"https://time.geekbang.org/column/intro/192",target:"_blank",rel:"noopener noreferrer"}},[t._v("极客时间 - SQL 必知必会"),a("OutboundLink")],1)])]),t._v(" "),a("h3",{attrs:{id:"order-by-是对分的组排序还是对分组中的记录排序呢"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#order-by-是对分的组排序还是对分组中的记录排序呢"}},[t._v("#")]),t._v(" ORDER BY 是对分的组排序还是对分组中的记录排序呢?")]),t._v(" "),a("p",[t._v("ORDER BY 就是对记录进行排序。如果你在 ORDER BY 前面用到了 GROUP BY,实际上这是一种分组的聚合方式,已经把一组的数据聚合成为了一条记录,再进行排序的时候,相当于对分的组进行了排序。")]),t._v(" "),a("h3",{attrs:{id:"select-语句内部的执行步骤"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#select-语句内部的执行步骤"}},[t._v("#")]),t._v(" SELECT 语句内部的执行步骤")]),t._v(" "),a("p",[t._v("一条完整的 SELECT 语句内部的执行顺序是这样的:")]),t._v(" "),a("ol",[a("li",[t._v("FROM 子句组装数据(包括通过 ON 进行连接);")]),t._v(" "),a("li",[t._v("WHERE 子句进行条件筛选;")]),t._v(" "),a("li",[t._v("GROUP BY 分组 ;")]),t._v(" "),a("li",[t._v("使用聚集函数进行计算;")]),t._v(" "),a("li",[t._v("HAVING 筛选分组;")]),t._v(" "),a("li",[t._v("计算所有的表达式;")]),t._v(" "),a("li",[t._v("SELECT 的字段;")]),t._v(" "),a("li",[t._v("ORDER BY 排序;")]),t._v(" "),a("li",[t._v("LIMIT 筛选。")])]),t._v(" "),a("blockquote",[a("p",[t._v("——摘自"),a("a",{attrs:{href:"https://time.geekbang.org/column/intro/192",target:"_blank",rel:"noopener noreferrer"}},[t._v("极客时间 - SQL 必知必会"),a("OutboundLink")],1)])]),t._v(" "),a("h3",{attrs:{id:"解哪种情况下应该使用-exists-哪种情况应该用-in"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#解哪种情况下应该使用-exists-哪种情况应该用-in"}},[t._v("#")]),t._v(" 解哪种情况下应该使用 EXISTS,哪种情况应该用 IN")]),t._v(" "),a("p",[t._v("索引是个前提,其实选择与否还是要看表的大小。你可以将选择的标准理解为小表驱动大表。在这种方式下效率是最高的。")]),t._v(" "),a("p",[t._v("比如下面这样:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v(" SELECT * FROM A WHERE cc IN (SELECT cc FROM B)\n SELECT * FROM A WHERE EXISTS (SELECT cc FROM B WHERE B.cc=A.cc)\n")])])]),a("p",[t._v("当 A 小于 B 时,用 EXISTS。因为 EXISTS 的实现,相当于外表循环,实现的逻辑类似于:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v(" for i in A\n for j in B\n if j.cc == i.cc then ...\n")])])]),a("p",[t._v("当 B 小于 A 时用 IN,因为实现的逻辑类似于:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v(" for i in B\n for j in A\n if j.cc == i.cc then ...\n")])])]),a("p",[t._v("哪个表小就用哪个表来驱动,A 表小就用 EXISTS,B 表小就用 IN。")]),t._v(" "),a("blockquote",[a("p",[t._v("——摘自"),a("a",{attrs:{href:"https://time.geekbang.org/column/intro/192",target:"_blank",rel:"noopener noreferrer"}},[t._v("极客时间 - SQL 必知必会"),a("OutboundLink")],1)])]),t._v(" "),a("h2",{attrs:{id:"参考资料"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#参考资料"}},[t._v("#")]),t._v(" 参考资料")]),t._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"https://juejin.im/post/5a9ca0d6518825555c1d1acd",target:"_blank",rel:"noopener noreferrer"}},[t._v("数据库面试题(开发者必看)"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/CyC2018/Interview-Notebook/blob/master/notes/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%B3%BB%E7%BB%9F%E5%8E%9F%E7%90%86.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("数据库系统原理"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://juejin.im/post/5b55b842f265da0f9e589e79",target:"_blank",rel:"noopener noreferrer"}},[t._v("数据库两大神器【索引和锁】"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://www.jianshu.com/p/32b3e91aa22c",target:"_blank",rel:"noopener noreferrer"}},[t._v("分库分表需要考虑的问题及方案"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://blog.csdn.net/bluishglc/article/details/7710738",target:"_blank",rel:"noopener noreferrer"}},[t._v("数据库分库分表(sharding)系列(二) 全局主键生成策略"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://blog.csdn.net/bluishglc/article/details/7970268",target:"_blank",rel:"noopener noreferrer"}},[t._v("一种支持自由规划无须数据迁移和修改路由代码的 Sharding 扩容方案"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://shardingsphere.apache.org/document/current/cn/features/transaction/",target:"_blank",rel:"noopener noreferrer"}},[t._v("ShardingSphere 分布式事务"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://zhuanlan.zhihu.com/p/39651803",target:"_blank",rel:"noopener noreferrer"}},[t._v("mysql 和 oracle 的区别"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://www.runoob.com/sql/sql-tutorial.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("RUNOOB SQL 教程"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://gameinstitute.qq.com/community/detail/107154",target:"_blank",rel:"noopener noreferrer"}},[t._v("如果有人问你数据库的原理,叫他看这篇文章"),a("OutboundLink")],1)])])])}),[],!1,null,null,null);a.default=v.exports}}]);
\ No newline at end of file
diff --git a/assets/js/13.a61047c2.js b/assets/js/13.a61047c2.js
new file mode 100644
index 00000000..bded4577
--- /dev/null
+++ b/assets/js/13.a61047c2.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{350:function(s,t,a){"use strict";a.r(t);var e=a(4),r=Object(e.a)({},(function(){var s=this,t=s._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":s.$parent.slotKey}},[t("h1",{attrs:{id:"sql-语法基础特性"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#sql-语法基础特性"}},[s._v("#")]),s._v(" SQL 语法基础特性")]),s._v(" "),t("blockquote",[t("p",[s._v("本文针对关系型数据库的基本语法。限于篇幅,本文侧重说明用法,不会展开讲解特性、原理。")]),s._v(" "),t("p",[s._v("本文语法主要针对 Mysql,但大部分的语法对其他关系型数据库也适用。")])]),s._v(" "),t("p",[t("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/snap/20200115160512.png",alt:"img"}})]),s._v(" "),t("h2",{attrs:{id:"sql-简介"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#sql-简介"}},[s._v("#")]),s._v(" SQL 简介")]),s._v(" "),t("h3",{attrs:{id:"数据库术语"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#数据库术语"}},[s._v("#")]),s._v(" 数据库术语")]),s._v(" "),t("ul",[t("li",[t("code",[s._v("数据库(database)")]),s._v(" - 保存有组织的数据的容器(通常是一个文件或一组文件)。")]),s._v(" "),t("li",[t("code",[s._v("数据表(table)")]),s._v(" - 某种特定类型数据的结构化清单。")]),s._v(" "),t("li",[t("code",[s._v("模式(schema)")]),s._v(" - 关于数据库和表的布局及特性的信息。模式定义了数据在表中如何存储,包含存储什么样的数据,数据如何分解,各部分信息如何命名等信息。数据库和表都有模式。")]),s._v(" "),t("li",[t("code",[s._v("列(column)")]),s._v(" - 表中的一个字段。所有表都是由一个或多个列组成的。")]),s._v(" "),t("li",[t("code",[s._v("行(row)")]),s._v(" - 表中的一个记录。")]),s._v(" "),t("li",[t("code",[s._v("主键(primary key)")]),s._v(" - 一列(或一组列),其值能够唯一标识表中每一行。")])]),s._v(" "),t("h3",{attrs:{id:"sql-语法"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#sql-语法"}},[s._v("#")]),s._v(" SQL 语法")]),s._v(" "),t("blockquote",[t("p",[s._v("SQL(Structured Query Language),标准 SQL 由 ANSI 标准委员会管理,从而称为 ANSI SQL。各个 DBMS 都有自己的实现,如 PL/SQL、Transact-SQL 等。")])]),s._v(" "),t("h4",{attrs:{id:"sql-语法结构"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#sql-语法结构"}},[s._v("#")]),s._v(" SQL 语法结构")]),s._v(" "),t("p",[t("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/master/cs/database/mysql/sql-syntax.png",alt:"img"}})]),s._v(" "),t("p",[s._v("SQL 语法结构包括:")]),s._v(" "),t("ul",[t("li",[t("strong",[t("code",[s._v("子句")])]),s._v(" - 是语句和查询的组成成分。(在某些情况下,这些都是可选的。)")]),s._v(" "),t("li",[t("strong",[t("code",[s._v("表达式")])]),s._v(" - 可以产生任何标量值,或由列和行的数据库表")]),s._v(" "),t("li",[t("strong",[t("code",[s._v("谓词")])]),s._v(" - 给需要评估的 SQL 三值逻辑(3VL)(true/false/unknown)或布尔真值指定条件,并限制语句和查询的效果,或改变程序流程。")]),s._v(" "),t("li",[t("strong",[t("code",[s._v("查询")])]),s._v(" - 基于特定条件检索数据。这是 SQL 的一个重要组成部分。")]),s._v(" "),t("li",[t("strong",[t("code",[s._v("语句")])]),s._v(" - 可以持久地影响纲要和数据,也可以控制数据库事务、程序流程、连接、会话或诊断。")])]),s._v(" "),t("h4",{attrs:{id:"sql-语法要点"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#sql-语法要点"}},[s._v("#")]),s._v(" SQL 语法要点")]),s._v(" "),t("ul",[t("li",[t("strong",[s._v("SQL 语句不区分大小写")]),s._v(",但是数据库表名、列名和值是否区分,依赖于具体的 DBMS 以及配置。")])]),s._v(" "),t("p",[s._v("例如:"),t("code",[s._v("SELECT")]),s._v(" 与 "),t("code",[s._v("select")]),s._v(" 、"),t("code",[s._v("Select")]),s._v(" 是相同的。")]),s._v(" "),t("ul",[t("li",[t("p",[t("strong",[s._v("多条 SQL 语句必须以分号("),t("code",[s._v(";")]),s._v(")分隔")]),s._v("。")])]),s._v(" "),t("li",[t("p",[s._v("处理 SQL 语句时,"),t("strong",[s._v("所有空格都被忽略")]),s._v("。SQL 语句可以写成一行,也可以分写为多行。")])])]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token comment"}},[s._v("-- 一行 SQL 语句")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("UPDATE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SET")]),s._v(" username"),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'robot'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" password"),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'robot'")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" username "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'root'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[s._v("-- 多行 SQL 语句")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("UPDATE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SET")]),s._v(" username"),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'robot'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" password"),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'robot'")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" username "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'root'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("ul",[t("li",[s._v("SQL 支持三种注释")])]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token comment"}},[s._v("## 注释1")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[s._v("-- 注释2")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[s._v("/* 注释3 */")]),s._v("\n")])])]),t("h4",{attrs:{id:"sql-分类"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#sql-分类"}},[s._v("#")]),s._v(" SQL 分类")]),s._v(" "),t("h4",{attrs:{id:"数据定义语言-ddl"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#数据定义语言-ddl"}},[s._v("#")]),s._v(" 数据定义语言(DDL)")]),s._v(" "),t("p",[s._v("数据定义语言(Data Definition Language,DDL)是 SQL 语言集中负责数据结构定义与数据库对象定义的语言。")]),s._v(" "),t("p",[s._v("DDL 的主要功能是"),t("strong",[s._v("定义数据库对象")]),s._v("。")]),s._v(" "),t("p",[s._v("DDL 的核心指令是 "),t("code",[s._v("CREATE")]),s._v("、"),t("code",[s._v("ALTER")]),s._v("、"),t("code",[s._v("DROP")]),s._v("。")]),s._v(" "),t("h4",{attrs:{id:"数据操纵语言-dml"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#数据操纵语言-dml"}},[s._v("#")]),s._v(" 数据操纵语言(DML)")]),s._v(" "),t("p",[s._v("数据操纵语言(Data Manipulation Language, DML)是用于数据库操作,对数据库其中的对象和数据运行访问工作的编程语句。")]),s._v(" "),t("p",[s._v("DML 的主要功能是 "),t("strong",[s._v("访问数据")]),s._v(",因此其语法都是以"),t("strong",[s._v("读写数据库")]),s._v("为主。")]),s._v(" "),t("p",[s._v("DML 的核心指令是 "),t("code",[s._v("INSERT")]),s._v("、"),t("code",[s._v("UPDATE")]),s._v("、"),t("code",[s._v("DELETE")]),s._v("、"),t("code",[s._v("SELECT")]),s._v("。这四个指令合称 CRUD(Create, Read, Update, Delete),即增删改查。")]),s._v(" "),t("h4",{attrs:{id:"事务控制语言-tcl"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#事务控制语言-tcl"}},[s._v("#")]),s._v(" 事务控制语言(TCL)")]),s._v(" "),t("p",[s._v("事务控制语言 (Transaction Control Language, TCL) 用于"),t("strong",[s._v("管理数据库中的事务")]),s._v("。这些用于管理由 DML 语句所做的更改。它还允许将语句分组为逻辑事务。")]),s._v(" "),t("p",[s._v("TCL 的核心指令是 "),t("code",[s._v("COMMIT")]),s._v("、"),t("code",[s._v("ROLLBACK")]),s._v("。")]),s._v(" "),t("h4",{attrs:{id:"数据控制语言-dcl"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#数据控制语言-dcl"}},[s._v("#")]),s._v(" 数据控制语言(DCL)")]),s._v(" "),t("p",[s._v("数据控制语言 (Data Control Language, DCL) 是一种可对数据访问权进行控制的指令,它可以控制特定用户账户对数据表、查看表、预存程序、用户自定义函数等数据库对象的控制权。")]),s._v(" "),t("p",[s._v("DCL 的核心指令是 "),t("code",[s._v("GRANT")]),s._v("、"),t("code",[s._v("REVOKE")]),s._v("。")]),s._v(" "),t("p",[s._v("DCL 以"),t("strong",[s._v("控制用户的访问权限")]),s._v("为主,因此其指令作法并不复杂,可利用 DCL 控制的权限有:"),t("code",[s._v("CONNECT")]),s._v("、"),t("code",[s._v("SELECT")]),s._v("、"),t("code",[s._v("INSERT")]),s._v("、"),t("code",[s._v("UPDATE")]),s._v("、"),t("code",[s._v("DELETE")]),s._v("、"),t("code",[s._v("EXECUTE")]),s._v("、"),t("code",[s._v("USAGE")]),s._v("、"),t("code",[s._v("REFERENCES")]),s._v("。")]),s._v(" "),t("p",[s._v("根据不同的 DBMS 以及不同的安全性实体,其支持的权限控制也有所不同。")]),s._v(" "),t("hr"),s._v(" "),t("p",[t("strong",[s._v("(以下为 DML 语句用法)")])]),s._v(" "),t("h2",{attrs:{id:"增删改查-crud"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#增删改查-crud"}},[s._v("#")]),s._v(" 增删改查(CRUD)")]),s._v(" "),t("p",[s._v("增删改查,又称为 "),t("strong",[t("code",[s._v("CRUD")])]),s._v(",是数据库基本操作中的基本操作。")]),s._v(" "),t("h3",{attrs:{id:"插入数据"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#插入数据"}},[s._v("#")]),s._v(" 插入数据")]),s._v(" "),t("blockquote",[t("ul",[t("li",[t("code",[s._v("INSERT INTO")]),s._v(" 语句用于向表中插入新记录。")])])]),s._v(" "),t("h4",{attrs:{id:"插入完整的行"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#插入完整的行"}},[s._v("#")]),s._v(" 插入完整的行")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("INSERT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("INTO")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("VALUES")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("10")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'root'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'root'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'xxxx@163.com'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"插入行的一部分"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#插入行的一部分"}},[s._v("#")]),s._v(" 插入行的一部分")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("INSERT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("INTO")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("username"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" password"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" email"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("VALUES")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'admin'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'admin'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'xxxx@163.com'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"插入查询出来的数据"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#插入查询出来的数据"}},[s._v("#")]),s._v(" 插入查询出来的数据")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("INSERT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("INTO")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("username"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" name\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" account"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h3",{attrs:{id:"更新数据"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#更新数据"}},[s._v("#")]),s._v(" 更新数据")]),s._v(" "),t("blockquote",[t("ul",[t("li",[t("code",[s._v("UPDATE")]),s._v(" 语句用于更新表中的记录。")])])]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("UPDATE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SET")]),s._v(" username"),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'robot'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" password"),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'robot'")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" username "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'root'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h3",{attrs:{id:"删除数据"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#删除数据"}},[s._v("#")]),s._v(" 删除数据")]),s._v(" "),t("blockquote",[t("ul",[t("li",[t("code",[s._v("DELETE")]),s._v(" 语句用于删除表中的记录。")]),s._v(" "),t("li",[t("code",[s._v("TRUNCATE TABLE")]),s._v(" 可以清空表,也就是删除所有行。")])])]),s._v(" "),t("h4",{attrs:{id:"删除表中的指定数据"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#删除表中的指定数据"}},[s._v("#")]),s._v(" 删除表中的指定数据")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DELETE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" username "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'robot'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"清空表中的数据"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#清空表中的数据"}},[s._v("#")]),s._v(" 清空表中的数据")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TRUNCATE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TABLE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h3",{attrs:{id:"查询数据"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#查询数据"}},[s._v("#")]),s._v(" 查询数据")]),s._v(" "),t("blockquote",[t("ul",[t("li",[t("code",[s._v("SELECT")]),s._v(" 语句用于从数据库中查询数据。")]),s._v(" "),t("li",[t("code",[s._v("DISTINCT")]),s._v(" 用于返回唯一不同的值。它作用于所有列,也就是说所有列的值都相同才算相同。")]),s._v(" "),t("li",[t("code",[s._v("LIMIT")]),s._v(" 限制返回的行数。可以有两个参数,第一个参数为起始行,从 0 开始;第二个参数为返回的总行数。\n"),t("ul",[t("li",[t("code",[s._v("ASC")]),s._v(" :升序(默认)")]),s._v(" "),t("li",[t("code",[s._v("DESC")]),s._v(" :降序")])])])])]),s._v(" "),t("h4",{attrs:{id:"查询单列"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#查询单列"}},[s._v("#")]),s._v(" 查询单列")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" prod_name "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"查询多列"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#查询多列"}},[s._v("#")]),s._v(" 查询多列")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" prod_id"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" prod_name"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" prod_price "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"查询所有列"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#查询所有列"}},[s._v("#")]),s._v(" 查询所有列")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("*")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"查询不同的值"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#查询不同的值"}},[s._v("#")]),s._v(" 查询不同的值")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DISTINCT")]),s._v(" vend_id "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"限制查询数量"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#限制查询数量"}},[s._v("#")]),s._v(" 限制查询数量")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token comment"}},[s._v("-- 返回前 5 行")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("*")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("LIMIT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("5")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("*")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("LIMIT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("0")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("5")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[s._v("-- 返回第 3 ~ 5 行")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("*")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("LIMIT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("2")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("3")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h2",{attrs:{id:"过滤数据-where"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#过滤数据-where"}},[s._v("#")]),s._v(" 过滤数据(WHERE)")]),s._v(" "),t("p",[s._v("子查询是嵌套在较大查询中的 SQL 查询。子查询也称为"),t("strong",[s._v("内部查询")]),s._v("或"),t("strong",[s._v("内部选择")]),s._v(",而包含子查询的语句也称为"),t("strong",[s._v("外部查询")]),s._v("或"),t("strong",[s._v("外部选择")]),s._v("。")]),s._v(" "),t("ul",[t("li",[t("p",[s._v("子查询可以嵌套在 "),t("code",[s._v("SELECT")]),s._v(","),t("code",[s._v("INSERT")]),s._v(","),t("code",[s._v("UPDATE")]),s._v(" 或 "),t("code",[s._v("DELETE")]),s._v(" 语句内或另一个子查询中。")])]),s._v(" "),t("li",[t("p",[s._v("子查询通常会在另一个 "),t("code",[s._v("SELECT")]),s._v(" 语句的 "),t("code",[s._v("WHERE")]),s._v(" 子句中添加。")])]),s._v(" "),t("li",[t("p",[s._v("您可以使用比较运算符,如 "),t("code",[s._v(">")]),s._v(","),t("code",[s._v("<")]),s._v(",或 "),t("code",[s._v("=")]),s._v("。比较运算符也可以是多行运算符,如 "),t("code",[s._v("IN")]),s._v(","),t("code",[s._v("ANY")]),s._v(" 或 "),t("code",[s._v("ALL")]),s._v("。")])]),s._v(" "),t("li",[t("p",[s._v("子查询必须被圆括号 "),t("code",[s._v("()")]),s._v(" 括起来。")])]),s._v(" "),t("li",[t("p",[s._v("内部查询首先在其父查询之前执行,以便可以将内部查询的结果传递给外部查询。执行过程可以参考下图:")]),s._v(" "),t("p",{attrs:{align:"center"}},[t("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/mysql/sql-subqueries.gif",alt:"sql-subqueries"}})])])]),s._v(" "),t("p",[t("strong",[s._v("子查询的子查询")])]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" cust_name"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" cust_contact\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" customers\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" cust_id "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("IN")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" cust_id\n "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" orders\n "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" order_num "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("IN")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" order_num\n "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" orderitems\n "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" prod_id "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'RGAN01'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h3",{attrs:{id:"where-子句"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#where-子句"}},[s._v("#")]),s._v(" WHERE 子句")]),s._v(" "),t("p",[s._v("在 SQL 语句中,数据根据 "),t("code",[s._v("WHERE")]),s._v(" 子句中指定的搜索条件进行过滤。")]),s._v(" "),t("p",[t("code",[s._v("WHERE")]),s._v(" 子句的基本格式如下:")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" ……"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("列名"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" ……"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("表名"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" ……"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("子句条件"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n")])])]),t("p",[t("code",[s._v("WHERE")]),s._v(" 子句用于过滤记录,即缩小访问数据的范围。"),t("code",[s._v("WHERE")]),s._v(" 后跟一个返回 "),t("code",[s._v("true")]),s._v(" 或 "),t("code",[s._v("false")]),s._v(" 的条件。")]),s._v(" "),t("p",[t("code",[s._v("WHERE")]),s._v(" 可以与 "),t("code",[s._v("SELECT")]),s._v(","),t("code",[s._v("UPDATE")]),s._v(" 和 "),t("code",[s._v("DELETE")]),s._v(" 一起使用。")]),s._v(" "),t("p",[t("strong",[t("code",[s._v("SELECT")]),s._v(" 语句中的 "),t("code",[s._v("WHERE")]),s._v(" 子句")])]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("*")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" Customers\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" cust_name "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'Kids Place'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("p",[t("strong",[t("code",[s._v("UPDATE")]),s._v(" 语句中的 "),t("code",[s._v("WHERE")]),s._v(" 子句")])]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("UPDATE")]),s._v(" Customers\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SET")]),s._v(" cust_name "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'Jack Jones'")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" cust_name "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'Kids Place'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("p",[t("strong",[t("code",[s._v("DELETE")]),s._v(" 语句中的 "),t("code",[s._v("WHERE")]),s._v(" 子句")])]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DELETE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" Customers\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" cust_name "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'Kids Place'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("p",[s._v("可以在 "),t("code",[s._v("WHERE")]),s._v(" 子句中使用的操作符:")]),s._v(" "),t("h3",{attrs:{id:"比较操作符"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#比较操作符"}},[s._v("#")]),s._v(" 比较操作符")]),s._v(" "),t("table",[t("thead",[t("tr",[t("th",[s._v("运算符")]),s._v(" "),t("th",[s._v("描述")])])]),s._v(" "),t("tbody",[t("tr",[t("td",[t("code",[s._v("=")])]),s._v(" "),t("td",[s._v("等于")])]),s._v(" "),t("tr",[t("td",[t("code",[s._v("<>")])]),s._v(" "),t("td",[s._v("不等于。注释:在 SQL 的一些版本中,该操作符可被写成 !=")])]),s._v(" "),t("tr",[t("td",[t("code",[s._v(">")])]),s._v(" "),t("td",[s._v("大于")])]),s._v(" "),t("tr",[t("td",[t("code",[s._v("<")])]),s._v(" "),t("td",[s._v("小于")])]),s._v(" "),t("tr",[t("td",[t("code",[s._v(">=")])]),s._v(" "),t("td",[s._v("大于等于")])]),s._v(" "),t("tr",[t("td",[t("code",[s._v("<=")])]),s._v(" "),t("td",[s._v("小于等于")])])])]),s._v(" "),t("h3",{attrs:{id:"范围操作符"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#范围操作符"}},[s._v("#")]),s._v(" 范围操作符")]),s._v(" "),t("table",[t("thead",[t("tr",[t("th",[s._v("运算符")]),s._v(" "),t("th",[s._v("描述")])])]),s._v(" "),t("tbody",[t("tr",[t("td",[t("code",[s._v("BETWEEN")])]),s._v(" "),t("td",[s._v("在某个范围内")])]),s._v(" "),t("tr",[t("td",[t("code",[s._v("IN")])]),s._v(" "),t("td",[s._v("指定针对某个列的多个可能值")])])])]),s._v(" "),t("ul",[t("li",[t("p",[t("code",[s._v("IN")]),s._v(" 操作符在 "),t("code",[s._v("WHERE")]),s._v(" 子句中使用,作用是在指定的几个特定值中任选一个值。")])]),s._v(" "),t("li",[t("p",[t("code",[s._v("BETWEEN")]),s._v(" 操作符在 "),t("code",[s._v("WHERE")]),s._v(" 子句中使用,作用是选取介于某个范围内的值。")])])]),s._v(" "),t("p",[t("strong",[s._v("IN 示例")])]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("*")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" vend_id "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("IN")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'DLL01'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'BRS01'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("p",[t("strong",[s._v("BETWEEN 示例")])]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("*")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" prod_price "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("BETWEEN")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("3")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("AND")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("5")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h3",{attrs:{id:"逻辑操作符"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#逻辑操作符"}},[s._v("#")]),s._v(" 逻辑操作符")]),s._v(" "),t("table",[t("thead",[t("tr",[t("th",[s._v("运算符")]),s._v(" "),t("th",[s._v("描述")])])]),s._v(" "),t("tbody",[t("tr",[t("td",[t("code",[s._v("AND")])]),s._v(" "),t("td",[s._v("并且(与)")])]),s._v(" "),t("tr",[t("td",[t("code",[s._v("OR")])]),s._v(" "),t("td",[s._v("或者(或)")])]),s._v(" "),t("tr",[t("td",[t("code",[s._v("NOT")])]),s._v(" "),t("td",[s._v("否定(非)")])])])]),s._v(" "),t("p",[t("code",[s._v("AND")]),s._v("、"),t("code",[s._v("OR")]),s._v("、"),t("code",[s._v("NOT")]),s._v(" 是用于对过滤条件的逻辑处理指令。")]),s._v(" "),t("ul",[t("li",[t("p",[t("code",[s._v("AND")]),s._v(" 优先级高于 "),t("code",[s._v("OR")]),s._v(",为了明确处理顺序,可以使用 "),t("code",[s._v("()")]),s._v("。"),t("code",[s._v("AND")]),s._v(" 操作符表示左右条件都要满足。")])]),s._v(" "),t("li",[t("p",[t("code",[s._v("OR")]),s._v(" 操作符表示左右条件满足任意一个即可。")])]),s._v(" "),t("li",[t("p",[t("code",[s._v("NOT")]),s._v(" 操作符用于否定一个条件。")])])]),s._v(" "),t("p",[t("strong",[s._v("AND 示例")])]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" prod_id"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" prod_name"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" prod_price\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" vend_id "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'DLL01'")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("AND")]),s._v(" prod_price "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("<=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("4")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("p",[t("strong",[s._v("OR 示例")])]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" prod_id"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" prod_name"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" prod_price\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" vend_id "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'DLL01'")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("OR")]),s._v(" vend_id "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'BRS01'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("p",[t("strong",[s._v("NOT 示例")])]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("*")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" prod_price "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("NOT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("BETWEEN")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("3")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("AND")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("5")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h3",{attrs:{id:"通配符"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#通配符"}},[s._v("#")]),s._v(" 通配符")]),s._v(" "),t("table",[t("thead",[t("tr",[t("th",[s._v("运算符")]),s._v(" "),t("th",[s._v("描述")])])]),s._v(" "),t("tbody",[t("tr",[t("td",[t("code",[s._v("LIKE")])]),s._v(" "),t("td",[s._v("搜索某种模式")])]),s._v(" "),t("tr",[t("td",[t("code",[s._v("%")])]),s._v(" "),t("td",[s._v("表示任意字符出现任意次数")])]),s._v(" "),t("tr",[t("td",[t("code",[s._v("_")])]),s._v(" "),t("td",[s._v("表示任意字符出现一次")])]),s._v(" "),t("tr",[t("td",[t("code",[s._v("[]")])]),s._v(" "),t("td",[s._v("必须匹配指定位置的一个字符")])])])]),s._v(" "),t("p",[t("code",[s._v("LIKE")]),s._v(" 操作符在 "),t("code",[s._v("WHERE")]),s._v(" 子句中使用,作用是确定字符串是否匹配模式。只有字段是文本值时才使用 "),t("code",[s._v("LIKE")]),s._v("。")]),s._v(" "),t("p",[t("code",[s._v("LIKE")]),s._v(" 支持以下通配符匹配选项:")]),s._v(" "),t("ul",[t("li",[t("code",[s._v("%")]),s._v(" 表示任何字符出现任意次数。")]),s._v(" "),t("li",[t("code",[s._v("_")]),s._v(" 表示任何字符出现一次。")]),s._v(" "),t("li",[t("code",[s._v("[]")]),s._v(" 必须匹配指定位置的一个字符。")])]),s._v(" "),t("blockquote",[t("p",[s._v("注意:"),t("strong",[s._v("不要滥用通配符,通配符位于开头处匹配会非常慢")]),s._v("。")])]),s._v(" "),t("p",[t("code",[s._v("%")]),s._v(" 示例:")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" prod_id"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" prod_name"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" prod_price\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" prod_name "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("LIKE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'%bean bag%'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("p",[t("code",[s._v("_")]),s._v(" 示例:")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" prod_id"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" prod_name"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" prod_price\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" prod_name "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("LIKE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'__ inch teddy bear'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("ul",[t("li")]),s._v(" "),t("h2",{attrs:{id:"排序-order-by"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#排序-order-by"}},[s._v("#")]),s._v(" 排序(ORDER BY)")]),s._v(" "),t("blockquote",[t("p",[t("code",[s._v("ORDER BY")]),s._v(" 用于对结果集进行排序。")])]),s._v(" "),t("p",[t("code",[s._v("ORDER BY")]),s._v(" 有两种排序模式:")]),s._v(" "),t("ul",[t("li",[t("code",[s._v("ASC")]),s._v(" :升序(默认)")]),s._v(" "),t("li",[t("code",[s._v("DESC")]),s._v(" :降序")])]),s._v(" "),t("p",[s._v("可以按多个列进行排序,并且为每个列指定不同的排序方式。")]),s._v(" "),t("p",[s._v("指定多个列的排序示例:")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("*")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" products\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ORDER")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("BY")]),s._v(" prod_price "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DESC")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" prod_name "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ASC")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h2",{attrs:{id:"数据定义-create、alter、drop"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#数据定义-create、alter、drop"}},[s._v("#")]),s._v(" 数据定义(CREATE、ALTER、DROP)")]),s._v(" "),t("blockquote",[t("p",[s._v("DDL 的主要功能是定义数据库对象(如:数据库、数据表、视图、索引等)。")])]),s._v(" "),t("h3",{attrs:{id:"数据库-database"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#数据库-database"}},[s._v("#")]),s._v(" 数据库(DATABASE)")]),s._v(" "),t("h4",{attrs:{id:"创建数据库"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#创建数据库"}},[s._v("#")]),s._v(" 创建数据库")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("CREATE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DATABASE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("IF")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("NOT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("EXISTS")]),s._v(" db_tutorial"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"删除数据库"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#删除数据库"}},[s._v("#")]),s._v(" 删除数据库")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DROP")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DATABASE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("IF")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("EXISTS")]),s._v(" db_tutorial"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"选择数据库"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#选择数据库"}},[s._v("#")]),s._v(" 选择数据库")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("USE")]),s._v(" db_tutorial"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h3",{attrs:{id:"数据表-table"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#数据表-table"}},[s._v("#")]),s._v(" 数据表(TABLE)")]),s._v(" "),t("h4",{attrs:{id:"删除数据表"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#删除数据表"}},[s._v("#")]),s._v(" 删除数据表")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DROP")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TABLE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("IF")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("EXISTS")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DROP")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TABLE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("IF")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("EXISTS")]),s._v(" vip_user"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"创建数据表"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#创建数据表"}},[s._v("#")]),s._v(" 创建数据表")]),s._v(" "),t("p",[t("strong",[s._v("普通创建")])]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("CREATE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TABLE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("\n id "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("INT")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("10")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("UNSIGNED")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("NOT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("NULL")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("COMMENT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'Id'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v("\n username "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("VARCHAR")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("64")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("NOT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("NULL")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DEFAULT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'default'")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("COMMENT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'用户名'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v("\n password "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("VARCHAR")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("64")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("NOT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("NULL")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DEFAULT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'default'")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("COMMENT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'密码'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v("\n email "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("VARCHAR")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("64")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("NOT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("NULL")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DEFAULT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'default'")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("COMMENT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'邮箱'")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("COMMENT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'用户表'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("p",[t("strong",[s._v("根据已有的表创建新表")])]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("CREATE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TABLE")]),s._v(" vip_user "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("AS")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("*")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"修改数据表"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#修改数据表"}},[s._v("#")]),s._v(" 修改数据表")]),s._v(" "),t("h5",{attrs:{id:"添加列"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#添加列"}},[s._v("#")]),s._v(" 添加列")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ALTER")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TABLE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ADD")]),s._v(" age "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("int")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("3")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h5",{attrs:{id:"删除列"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#删除列"}},[s._v("#")]),s._v(" 删除列")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ALTER")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TABLE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DROP")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("COLUMN")]),s._v(" age"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h5",{attrs:{id:"修改列"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#修改列"}},[s._v("#")]),s._v(" 修改列")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ALTER")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TABLE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token identifier"}},[t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("`")]),s._v("user"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("`")])]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("MODIFY")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("COLUMN")]),s._v(" age "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("tinyint")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h3",{attrs:{id:"视图-view"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#视图-view"}},[s._v("#")]),s._v(" 视图(VIEW)")]),s._v(" "),t("blockquote",[t("p",[s._v("视图是基于 SQL 语句的结果集的可视化的表。"),t("strong",[s._v("视图是虚拟的表,本身不存储数据,也就不能对其进行索引操作")]),s._v("。对视图的操作和对普通表的操作一样。")])]),s._v(" "),t("p",[s._v("视图的作用:")]),s._v(" "),t("ul",[t("li",[s._v("简化复杂的 SQL 操作,比如复杂的连接。")]),s._v(" "),t("li",[s._v("只使用实际表的一部分数据。")]),s._v(" "),t("li",[s._v("通过只给用户访问视图的权限,保证数据的安全性。")]),s._v(" "),t("li",[s._v("更改数据格式和表示。")])]),s._v(" "),t("h4",{attrs:{id:"创建视图"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#创建视图"}},[s._v("#")]),s._v(" 创建视图")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("CREATE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("VIEW")]),s._v(" top_10_user_view "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("AS")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" id"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v(" username\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" id "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("<")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("10")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"删除视图"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#删除视图"}},[s._v("#")]),s._v(" 删除视图")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DROP")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("VIEW")]),s._v(" top_10_user_view"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h3",{attrs:{id:"索引-index"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#索引-index"}},[s._v("#")]),s._v(" 索引(INDEX)")]),s._v(" "),t("blockquote",[t("p",[s._v("通过索引可以更加快速高效地查询数据。用户无法看到索引,它们只能被用来加速查询。")])]),s._v(" "),t("p",[s._v("更新一个包含索引的表需要比更新一个没有索引的表花费更多的时间,这是由于索引本身也需要更新。因此,理想的做法是仅仅在常常被搜索的列(以及表)上面创建索引。")]),s._v(" "),t("p",[s._v("唯一索引:唯一索引表明此索引的每一个索引值只对应唯一的数据记录。")]),s._v(" "),t("h4",{attrs:{id:"创建索引"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#创建索引"}},[s._v("#")]),s._v(" 创建索引")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("CREATE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("INDEX")]),s._v(" idx_email\n "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ON")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("email"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"创建唯一索引"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#创建唯一索引"}},[s._v("#")]),s._v(" 创建唯一索引")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("CREATE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("UNIQUE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("INDEX")]),s._v(" uniq_username\n "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ON")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("username"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"删除索引"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#删除索引"}},[s._v("#")]),s._v(" 删除索引")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ALTER")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TABLE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DROP")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("INDEX")]),s._v(" idx_email"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ALTER")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TABLE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DROP")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("INDEX")]),s._v(" uniq_username"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"添加主键"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#添加主键"}},[s._v("#")]),s._v(" 添加主键")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ALTER")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TABLE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ADD")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("PRIMARY")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("KEY")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("id"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h4",{attrs:{id:"删除主键"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#删除主键"}},[s._v("#")]),s._v(" 删除主键")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ALTER")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TABLE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("user")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DROP")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("PRIMARY")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("KEY")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h3",{attrs:{id:"约束"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#约束"}},[s._v("#")]),s._v(" 约束")]),s._v(" "),t("blockquote",[t("p",[s._v("SQL 约束用于规定表中的数据规则。")])]),s._v(" "),t("ul",[t("li",[s._v("如果存在违反约束的数据行为,行为会被约束终止。")]),s._v(" "),t("li",[s._v("约束可以在创建表时规定(通过 CREATE TABLE 语句),或者在表创建之后规定(通过 ALTER TABLE 语句)。")]),s._v(" "),t("li",[s._v("约束类型\n"),t("ul",[t("li",[t("code",[s._v("NOT NULL")]),s._v(" - 指示某列不能存储 NULL 值。")]),s._v(" "),t("li",[t("code",[s._v("UNIQUE")]),s._v(" - 保证某列的每行必须有唯一的值。")]),s._v(" "),t("li",[t("code",[s._v("PRIMARY KEY")]),s._v(" - NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。")]),s._v(" "),t("li",[t("code",[s._v("FOREIGN KEY")]),s._v(" - 保证一个表中的数据匹配另一个表中的值的参照完整性。")]),s._v(" "),t("li",[t("code",[s._v("CHECK")]),s._v(" - 保证列中的值符合指定的条件。")]),s._v(" "),t("li",[t("code",[s._v("DEFAULT")]),s._v(" - 规定没有给列赋值时的默认值。")])])])]),s._v(" "),t("p",[s._v("创建表时使用约束条件:")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("CREATE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TABLE")]),s._v(" Users "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("\n Id "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("INT")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("10")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("UNSIGNED")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("NOT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("NULL")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("AUTO_INCREMENT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("COMMENT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'自增Id'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v("\n Username "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("VARCHAR")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("64")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("NOT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("NULL")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("UNIQUE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DEFAULT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'default'")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("COMMENT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'用户名'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v("\n Password "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("VARCHAR")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("64")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("NOT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("NULL")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DEFAULT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'default'")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("COMMENT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'密码'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v("\n Email "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("VARCHAR")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("64")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("NOT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("NULL")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DEFAULT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'default'")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("COMMENT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'邮箱地址'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v("\n Enabled "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TINYINT")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("4")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DEFAULT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("NULL")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("COMMENT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'是否有效'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),s._v("\n "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("PRIMARY")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("KEY")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("Id"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ENGINE")]),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("InnoDB")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("AUTO_INCREMENT")]),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("2")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("DEFAULT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("CHARSET")]),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v("utf8mb4 "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("COMMENT")]),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'用户表'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h2",{attrs:{id:"参考资料"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#参考资料"}},[s._v("#")]),s._v(" 参考资料")]),s._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://book.douban.com/subject/35167240/",target:"_blank",rel:"noopener noreferrer"}},[s._v("《SQL 必知必会》"),t("OutboundLink")],1)]),s._v(" "),t("li",[t("a",{attrs:{href:"https://draveness.me/mysql-transaction",target:"_blank",rel:"noopener noreferrer"}},[s._v("『浅入深出』MySQL 中事务的实现"),t("OutboundLink")],1)]),s._v(" "),t("li",[t("a",{attrs:{href:"https://www.cnblogs.com/CraryPrimitiveMan/p/4206942.html",target:"_blank",rel:"noopener noreferrer"}},[s._v("MySQL 的学习--触发器"),t("OutboundLink")],1)]),s._v(" "),t("li",[t("a",{attrs:{href:"https://zh.wikipedia.org/wiki/SQL",target:"_blank",rel:"noopener noreferrer"}},[s._v("维基百科词条 - SQL"),t("OutboundLink")],1)]),s._v(" "),t("li",[t("a",{attrs:{href:"https://www.sitesbay.com/sql/index",target:"_blank",rel:"noopener noreferrer"}},[s._v("https://www.sitesbay.com/sql/index"),t("OutboundLink")],1)]),s._v(" "),t("li",[t("a",{attrs:{href:"https://www.w3resource.com/sql/subqueries/understanding-sql-subqueries.php",target:"_blank",rel:"noopener noreferrer"}},[s._v("SQL Subqueries"),t("OutboundLink")],1)]),s._v(" "),t("li",[t("a",{attrs:{href:"https://stackoverflow.com/questions/6294778/mysql-quick-breakdown-of-the-types-of-joins",target:"_blank",rel:"noopener noreferrer"}},[s._v("Quick breakdown of the types of joins"),t("OutboundLink")],1)]),s._v(" "),t("li",[t("a",{attrs:{href:"https://www.w3resource.com/sql/sql-union.php",target:"_blank",rel:"noopener noreferrer"}},[s._v("SQL UNION"),t("OutboundLink")],1)]),s._v(" "),t("li",[t("a",{attrs:{href:"https://www.w3resource.com/sql/database-security/create-users.php",target:"_blank",rel:"noopener noreferrer"}},[s._v("SQL database security"),t("OutboundLink")],1)]),s._v(" "),t("li",[t("a",{attrs:{href:"https://www.cnblogs.com/chenpi/p/5136483.html",target:"_blank",rel:"noopener noreferrer"}},[s._v("Mysql 中的存储过程"),t("OutboundLink")],1)])])])}),[],!1,null,null,null);t.default=r.exports}}]);
\ No newline at end of file
diff --git a/assets/js/14.06d1916b.js b/assets/js/14.06d1916b.js
new file mode 100644
index 00000000..864e7a1c
--- /dev/null
+++ b/assets/js/14.06d1916b.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{351:function(t,s,a){"use strict";a.r(s);var e=a(4),n=Object(e.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"sql-语法高级特性"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#sql-语法高级特性"}},[t._v("#")]),t._v(" SQL 语法高级特性")]),t._v(" "),s("blockquote",[s("p",[t._v("本文针对关系型数据库的基本语法。限于篇幅,本文侧重说明用法,不会展开讲解特性、原理。")]),t._v(" "),s("p",[t._v("本文语法主要针对 Mysql,但大部分的语法对其他关系型数据库也适用。")])]),t._v(" "),s("p",[s("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/snap/20200115160512.png",alt:"img"}})]),t._v(" "),s("h2",{attrs:{id:"连接和组合"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#连接和组合"}},[t._v("#")]),t._v(" 连接和组合")]),t._v(" "),s("h3",{attrs:{id:"连接-join"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#连接-join"}},[t._v("#")]),t._v(" 连接(JOIN)")]),t._v(" "),s("blockquote",[s("p",[t._v("连接用于连接多个表,使用 "),s("code",[t._v("JOIN")]),t._v(" 关键字,并且条件语句使用 "),s("code",[t._v("ON")]),t._v(" 而不是 "),s("code",[t._v("WHERE")]),t._v("。")])]),t._v(" "),s("p",[t._v("如果一个 "),s("code",[t._v("JOIN")]),t._v(" 至少有一个公共字段并且它们之间存在关系,则该 "),s("code",[t._v("JOIN")]),t._v(" 可以在两个或多个表上工作。")]),t._v(" "),s("p",[s("code",[t._v("JOIN")]),t._v(" 保持基表(结构和数据)不变。"),s("strong",[t._v("连接可以替换子查询,并且比子查询的效率一般会更快")]),t._v("。")]),t._v(" "),s("p",[s("code",[t._v("JOIN")]),t._v(" 有两种连接类型:内连接和外连接。")]),t._v(" "),s("div",{attrs:{align:"center"}},[s("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/mysql/sql-join.png",alt:"sql-join"}})]),t._v(" "),s("h4",{attrs:{id:"内连接-inner-join"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#内连接-inner-join"}},[t._v("#")]),t._v(" 内连接(INNER JOIN)")]),t._v(" "),s("p",[t._v("内连接又称等值连接,"),s("strong",[t._v("使用 "),s("code",[t._v("INNER JOIN")]),t._v(" 关键字")]),t._v("。在没有条件语句的情况下"),s("strong",[t._v("返回笛卡尔积")]),t._v("。")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" vend_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" prod_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" prod_price\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" vendors "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INNER")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("JOIN")]),t._v(" products\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ON")]),t._v(" vendors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("vend_id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" products"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("vend_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h5",{attrs:{id:"自连接"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#自连接"}},[t._v("#")]),t._v(" 自连接("),s("code",[t._v("=")]),t._v(")")]),t._v(" "),s("p",[t._v("自连接可以看成内连接的一种,只是"),s("strong",[t._v("连接的表是自身")]),t._v("而已。"),s("strong",[t._v("自然连接是把同名列通过 "),s("code",[t._v("=")]),t._v(" 连接起来")]),t._v("的,同名列可以有多个。")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" c1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cust_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" c1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cust_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" c1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cust_contact\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" customers c1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" customers c2\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" c1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cust_name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" c2"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cust_name\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("AND")]),t._v(" c2"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cust_contact "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'Jim Jones'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h5",{attrs:{id:"自然连接-natural-join"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#自然连接-natural-join"}},[t._v("#")]),t._v(" 自然连接(NATURAL JOIN)")]),t._v(" "),s("p",[t._v("内连接提供连接的列,而自然连接"),s("strong",[t._v("自动连接所有同名列")]),t._v("。自然连接使用 "),s("code",[t._v("NATURAL JOIN")]),t._v(" 关键字。")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" Products\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("NATURAL")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("JOIN")]),t._v(" Customers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h4",{attrs:{id:"外连接-outer-join"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#外连接-outer-join"}},[t._v("#")]),t._v(" 外连接(OUTER JOIN)")]),t._v(" "),s("p",[t._v("外连接返回一个表中的所有行,并且仅返回来自此表中满足连接条件的那些行,即两个表中的列是相等的。外连接分为左外连接、右外连接、全外连接(Mysql 不支持)。")]),t._v(" "),s("h5",{attrs:{id:"左连接-left-join"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#左连接-left-join"}},[t._v("#")]),t._v(" 左连接(LEFT JOIN)")]),t._v(" "),s("p",[t._v("左外连接就是保留左表没有关联的行。")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" customers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cust_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" orders"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("order_num\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" customers "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("LEFT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("JOIN")]),t._v(" orders\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ON")]),t._v(" customers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cust_id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" orders"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cust_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h5",{attrs:{id:"右连接-right-join"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#右连接-right-join"}},[t._v("#")]),t._v(" 右连接(RIGHT JOIN)")]),t._v(" "),s("p",[t._v("右外连接就是保留右表没有关联的行。")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" customers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cust_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" orders"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("order_num\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" customers "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("RIGHT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("JOIN")]),t._v(" orders\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ON")]),t._v(" customers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cust_id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" orders"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cust_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h3",{attrs:{id:"组合-union"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#组合-union"}},[t._v("#")]),t._v(" 组合(UNION)")]),t._v(" "),s("blockquote",[s("p",[s("code",[t._v("UNION")]),t._v(" 运算符"),s("strong",[t._v("将两个或更多查询的结果组合起来,并生成一个结果集")]),t._v(",其中包含来自 "),s("code",[t._v("UNION")]),t._v(" 中参与查询的提取行。")])]),t._v(" "),s("p",[s("code",[t._v("UNION")]),t._v(" 基本规则:")]),t._v(" "),s("ul",[s("li",[t._v("所有查询的列数和列顺序必须相同。")]),t._v(" "),s("li",[t._v("每个查询中涉及表的列的数据类型必须相同或兼容。")]),t._v(" "),s("li",[t._v("通常返回的列名取自第一个查询。")])]),t._v(" "),s("p",[t._v("默认会去除相同行,如果需要保留相同行,使用 "),s("code",[t._v("UNION ALL")]),t._v("。")]),t._v(" "),s("p",[t._v("只能包含一个 "),s("code",[t._v("ORDER BY")]),t._v(" 子句,并且必须位于语句的最后。")]),t._v(" "),s("p",[t._v("应用场景:")]),t._v(" "),s("ul",[s("li",[t._v("在一个查询中从不同的表返回结构数据。")]),t._v(" "),s("li",[t._v("对一个表执行多个查询,按一个查询返回数据。")])]),t._v(" "),s("p",[t._v("组合查询示例:")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" cust_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cust_contact"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cust_email\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" customers\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" cust_state "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("IN")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'IL'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'IN'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'MI'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("UNION")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" cust_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cust_contact"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cust_email\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" customers\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" cust_name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'Fun4All'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h3",{attrs:{id:"join-vs-union"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#join-vs-union"}},[t._v("#")]),t._v(" JOIN vs UNION")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("JOIN")]),t._v(" 中连接表的列可能不同,但在 "),s("code",[t._v("UNION")]),t._v(" 中,所有查询的列数和列顺序必须相同。")]),t._v(" "),s("li",[s("code",[t._v("UNION")]),t._v(" 将查询之后的行放在一起(垂直放置),但 "),s("code",[t._v("JOIN")]),t._v(" 将查询之后的列放在一起(水平放置),即它构成一个笛卡尔积。")])]),t._v(" "),s("h2",{attrs:{id:"函数"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#函数"}},[t._v("#")]),t._v(" 函数")]),t._v(" "),s("blockquote",[s("p",[t._v("🔔 注意:不同数据库的函数往往各不相同,因此不可移植。本节主要以 Mysql 的函数为例。")])]),t._v(" "),s("h3",{attrs:{id:"文本处理"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#文本处理"}},[t._v("#")]),t._v(" 文本处理")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",{staticStyle:{"text-align":"center"}},[t._v("函数")]),t._v(" "),s("th",{staticStyle:{"text-align":"center"}},[t._v("说明")])])]),t._v(" "),s("tbody",[s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("LEFT()")]),t._v("、"),s("code",[t._v("RIGHT()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("左边或者右边的字符")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("LOWER()")]),t._v("、"),s("code",[t._v("UPPER()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("转换为小写或者大写")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("LTRIM()")]),t._v("、"),s("code",[t._v("RTIM()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("去除左边或者右边的空格")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("LENGTH()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("长度")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("SOUNDEX()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("转换为语音值")])])])]),t._v(" "),s("p",[t._v("其中, "),s("strong",[t._v("SOUNDEX()")]),t._v(" 可以将一个字符串转换为描述其语音表示的字母数字模式。")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" mytable\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" SOUNDEX"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("col1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SOUNDEX"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'apple'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h3",{attrs:{id:"日期和时间处理"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#日期和时间处理"}},[t._v("#")]),t._v(" 日期和时间处理")]),t._v(" "),s("ul",[s("li",[t._v("日期格式:"),s("code",[t._v("YYYY-MM-DD")])]),t._v(" "),s("li",[t._v("时间格式:"),s("code",[t._v("HH:MM:SS")])])]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",{staticStyle:{"text-align":"center"}},[t._v("函 数")]),t._v(" "),s("th",{staticStyle:{"text-align":"center"}},[t._v("说 明")])])]),t._v(" "),s("tbody",[s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("AddDate()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("增加一个日期(天、周等)")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("AddTime()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("增加一个时间(时、分等)")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("CurDate()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回当前日期")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("CurTime()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回当前时间")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("Date()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回日期时间的日期部分")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("DateDiff()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("计算两个日期之差")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("Date_Add()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("高度灵活的日期运算函数")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("Date_Format()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回一个格式化的日期或时间串")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("Day()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回一个日期的天数部分")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("DayOfWeek()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("对于一个日期,返回对应的星期几")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("Hour()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回一个时间的小时部分")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("Minute()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回一个时间的分钟部分")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("Month()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回一个日期的月份部分")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("Now()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回当前日期和时间")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("Second()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回一个时间的秒部分")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("Time()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回一个日期时间的时间部分")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("Year()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回一个日期的年份部分")])])])]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[t._v("mysql"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("NOW")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("2018-4-14 20:25:11\n")])])]),s("h3",{attrs:{id:"数值处理"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#数值处理"}},[t._v("#")]),t._v(" 数值处理")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",{staticStyle:{"text-align":"center"}},[t._v("函数")]),t._v(" "),s("th",{staticStyle:{"text-align":"center"}},[t._v("说明")])])]),t._v(" "),s("tbody",[s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("SIN()")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("正弦")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("COS()")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("余弦")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("TAN()")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("正切")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("ABS()")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("绝对值")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("SQRT()")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("平方根")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("MOD()")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("余数")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("EXP()")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("指数")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("PI()")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("圆周率")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("RAND()")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("随机数")])])])]),t._v(" "),s("h3",{attrs:{id:"汇总"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#汇总"}},[t._v("#")]),t._v(" 汇总")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",{staticStyle:{"text-align":"center"}},[t._v("函 数")]),t._v(" "),s("th",{staticStyle:{"text-align":"center"}},[t._v("说 明")])])]),t._v(" "),s("tbody",[s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("AVG()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回某列的平均值")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("COUNT()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回某列的行数")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("MAX()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回某列的最大值")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("MIN()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回某列的最小值")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[s("code",[t._v("SUM()")])]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("返回某列值之和")])])])]),t._v(" "),s("p",[s("code",[t._v("AVG()")]),t._v(" 会忽略 NULL 行。")]),t._v(" "),s("p",[t._v("使用 DISTINCT 可以让汇总函数值汇总不同的值。")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("AVG")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DISTINCT")]),t._v(" col1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("AS")]),t._v(" avg_col\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" mytable\n")])])]),s("h2",{attrs:{id:"分组"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#分组"}},[t._v("#")]),t._v(" 分组")]),t._v(" "),s("h3",{attrs:{id:"group-by"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#group-by"}},[t._v("#")]),t._v(" GROUP BY")]),t._v(" "),s("blockquote",[s("p",[s("code",[t._v("GROUP BY")]),t._v(" 子句将记录分组到汇总行中,"),s("code",[t._v("GROUP BY")]),t._v(" 为每个组返回一个记录。")])]),t._v(" "),s("p",[s("code",[t._v("GROUP BY")]),t._v(" 可以按一列或多列进行分组。")]),t._v(" "),s("p",[s("code",[t._v("GROUP BY")]),t._v(" 通常还涉及聚合函数:COUNT,MAX,SUM,AVG 等。")]),t._v(" "),s("p",[s("code",[t._v("GROUP BY")]),t._v(" 按分组字段进行排序后,"),s("code",[t._v("ORDER BY")]),t._v(" 可以以汇总字段来进行排序。")]),t._v(" "),s("p",[t._v("分组示例:")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" cust_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("COUNT")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cust_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("AS")]),t._v(" addr_num\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" Customers "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("GROUP")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("BY")]),t._v(" cust_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("p",[t._v("分组后排序示例:")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" cust_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("COUNT")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cust_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("AS")]),t._v(" addr_num\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" Customers "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("GROUP")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("BY")]),t._v(" cust_name\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ORDER")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("BY")]),t._v(" cust_name "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DESC")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h3",{attrs:{id:"having"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#having"}},[t._v("#")]),t._v(" HAVING")]),t._v(" "),s("blockquote",[s("p",[s("code",[t._v("HAVING")]),t._v(" 用于对汇总的 "),s("code",[t._v("GROUP BY")]),t._v(" 结果进行过滤。"),s("code",[t._v("HAVING")]),t._v(" 要求存在一个 "),s("code",[t._v("GROUP BY")]),t._v(" 子句。")])]),t._v(" "),s("p",[s("code",[t._v("WHERE")]),t._v(" 和 "),s("code",[t._v("HAVING")]),t._v(" 可以在相同的查询中。")]),t._v(" "),s("p",[s("code",[t._v("HAVING")]),t._v(" vs "),s("code",[t._v("WHERE")]),t._v(":")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("WHERE")]),t._v(" 和 "),s("code",[t._v("HAVING")]),t._v(" 都是用于过滤。")]),t._v(" "),s("li",[s("code",[t._v("HAVING")]),t._v(" 适用于汇总的组记录;而 "),s("code",[t._v("WHERE")]),t._v(" 适用于单个记录。")])]),t._v(" "),s("p",[t._v("使用 "),s("code",[t._v("WHERE")]),t._v(" 和 "),s("code",[t._v("HAVING")]),t._v(" 过滤数据示例:")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" cust_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("COUNT")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("AS")]),t._v(" num\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" Customers\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" cust_email "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("IS")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("NOT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("NULL")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("GROUP")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("BY")]),t._v(" cust_name\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("HAVING")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("COUNT")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("hr"),t._v(" "),s("p",[s("strong",[t._v("(以下为 DDL 语句用法)")])]),t._v(" "),s("h2",{attrs:{id:"事务"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#事务"}},[t._v("#")]),t._v(" 事务")]),t._v(" "),s("p",[t._v("不能回退 "),s("code",[t._v("SELECT")]),t._v(" 语句,回退 "),s("code",[t._v("SELECT")]),t._v(" 语句也没意义;也不能回退 "),s("code",[t._v("CREATE")]),t._v(" 和 "),s("code",[t._v("DROP")]),t._v(" 语句。")]),t._v(" "),s("p",[s("strong",[t._v("MySQL 默认采用隐式提交策略("),s("code",[t._v("autocommit")]),t._v(")")]),t._v(",每执行一条语句就把这条语句当成一个事务然后进行提交。当出现 "),s("code",[t._v("START TRANSACTION")]),t._v(" 语句时,会关闭隐式提交;当 "),s("code",[t._v("COMMIT")]),t._v(" 或 "),s("code",[t._v("ROLLBACK")]),t._v(" 语句执行后,事务会自动关闭,重新恢复隐式提交。")]),t._v(" "),s("p",[t._v("通过 "),s("code",[t._v("set autocommit=0")]),t._v(" 可以取消自动提交,直到 "),s("code",[t._v("set autocommit=1")]),t._v(" 才会提交;"),s("code",[t._v("autocommit")]),t._v(" 标记是针对每个连接而不是针对服务器的。")]),t._v(" "),s("p",[t._v("事务处理指令:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("START TRANSACTION")]),t._v(" - 指令用于标记事务的起始点。")]),t._v(" "),s("li",[s("code",[t._v("SAVEPOINT")]),t._v(" - 指令用于创建保留点。")]),t._v(" "),s("li",[s("code",[t._v("ROLLBACK TO")]),t._v(" - 指令用于回滚到指定的保留点;如果没有设置保留点,则回退到 "),s("code",[t._v("START TRANSACTION")]),t._v(" 语句处。")]),t._v(" "),s("li",[s("code",[t._v("COMMIT")]),t._v(" - 提交事务。")]),t._v(" "),s("li",[s("code",[t._v("RELEASE SAVEPOINT")]),t._v(":删除某个保存点。")]),t._v(" "),s("li",[s("code",[t._v("SET TRANSACTION")]),t._v(":设置事务的隔离级别。")])]),t._v(" "),s("p",[t._v("事务处理示例:")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- 开始事务")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("START")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("TRANSACTION")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- 插入操作 A")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INSERT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INTO")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token identifier"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")])]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("VALUES")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'root1'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'root1'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'xxxx@163.com'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- 创建保留点 updateA")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SAVEPOINT")]),t._v(" updateA"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- 插入操作 B")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INSERT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INTO")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token identifier"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")])]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("VALUES")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'root2'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'root2'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'xxxx@163.com'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- 回滚到保留点 updateA")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ROLLBACK")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("TO")]),t._v(" updateA"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- 提交事务,只有操作 A 生效")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("COMMIT")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h3",{attrs:{id:"acid"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#acid"}},[t._v("#")]),t._v(" ACID")]),t._v(" "),s("h3",{attrs:{id:"事务隔离级别"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#事务隔离级别"}},[t._v("#")]),t._v(" 事务隔离级别")]),t._v(" "),s("hr"),t._v(" "),s("p",[s("strong",[t._v("(以下为 DCL 语句用法)")])]),t._v(" "),s("h2",{attrs:{id:"权限控制"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#权限控制"}},[t._v("#")]),t._v(" 权限控制")]),t._v(" "),s("p",[s("code",[t._v("GRANT")]),t._v(" 和 "),s("code",[t._v("REVOKE")]),t._v(" 可在几个层次上控制访问权限:")]),t._v(" "),s("ul",[s("li",[t._v("整个服务器,使用 "),s("code",[t._v("GRANT ALL")]),t._v(" 和 "),s("code",[t._v("REVOKE ALL")]),t._v(";")]),t._v(" "),s("li",[t._v("整个数据库,使用 ON database.*;")]),t._v(" "),s("li",[t._v("特定的表,使用 ON database.table;")]),t._v(" "),s("li",[t._v("特定的列;")]),t._v(" "),s("li",[t._v("特定的存储过程。")])]),t._v(" "),s("p",[t._v("新创建的账户没有任何权限。")]),t._v(" "),s("p",[t._v("账户用 "),s("code",[t._v("username@host")]),t._v(" 的形式定义,"),s("code",[t._v("username@%")]),t._v(" 使用的是默认主机名。")]),t._v(" "),s("p",[t._v("MySQL 的账户信息保存在 mysql 这个数据库中。")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("USE")]),t._v(" mysql"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("user")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("user")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h3",{attrs:{id:"创建账户"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#创建账户"}},[t._v("#")]),t._v(" 创建账户")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("CREATE")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("USER")]),t._v(" myuser IDENTIFIED "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("BY")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'mypassword'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h3",{attrs:{id:"修改账户名"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#修改账户名"}},[t._v("#")]),t._v(" 修改账户名")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("UPDATE")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("user")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SET")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("user")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'newuser'")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHERE")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("user")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'myuser'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\nFLUSH "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("PRIVILEGES")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h3",{attrs:{id:"删除账户"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#删除账户"}},[t._v("#")]),t._v(" 删除账户")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DROP")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("USER")]),t._v(" myuser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h3",{attrs:{id:"查看权限"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#查看权限"}},[t._v("#")]),t._v(" 查看权限")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SHOW")]),t._v(" GRANTS "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FOR")]),t._v(" myuser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h3",{attrs:{id:"授予权限"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#授予权限"}},[t._v("#")]),t._v(" 授予权限")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("GRANT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INSERT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ON")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("TO")]),t._v(" myuser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h3",{attrs:{id:"删除权限"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#删除权限"}},[t._v("#")]),t._v(" 删除权限")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("REVOKE")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INSERT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ON")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FROM")]),t._v(" myuser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h3",{attrs:{id:"更改密码"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#更改密码"}},[t._v("#")]),t._v(" 更改密码")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SET")]),t._v(" PASSWORD "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FOR")]),t._v(" myuser "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'mypass'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h2",{attrs:{id:"存储过程"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#存储过程"}},[t._v("#")]),t._v(" 存储过程")]),t._v(" "),s("p",[t._v("存储过程的英文是 Stored Procedure。它可以视为一组 SQL 语句的批处理。一旦存储过程被创建出来,使用它就像使用函数一样简单,我们直接通过调用存储过程名即可。")]),t._v(" "),s("p",[t._v("定义存储过程的语法格式:")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("CREATE")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("PROCEDURE")]),t._v(" 存储过程名称 "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("参数列表"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("BEGIN")]),t._v("\n 需要执行的语句\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("END")]),t._v("\n")])])]),s("p",[t._v("存储过程定义语句类型:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("CREATE PROCEDURE")]),t._v(" 用于创建存储过程")]),t._v(" "),s("li",[s("code",[t._v("DROP PROCEDURE")]),t._v(" 用于删除存储过程")]),t._v(" "),s("li",[s("code",[t._v("ALTER PROCEDURE")]),t._v(" 用于修改存储过程")])]),t._v(" "),s("h3",{attrs:{id:"使用存储过程"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#使用存储过程"}},[t._v("#")]),t._v(" 使用存储过程")]),t._v(" "),s("p",[t._v("创建存储过程的要点:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("DELIMITER")]),t._v(" 用于定义语句的结束符")]),t._v(" "),s("li",[t._v("存储过程的 3 种参数类型:\n"),s("ul",[s("li",[s("code",[t._v("IN")]),t._v(":存储过程的入参")]),t._v(" "),s("li",[s("code",[t._v("OUT")]),t._v(":存储过程的出参")]),t._v(" "),s("li",[s("code",[t._v("INPUT")]),t._v(":既是存储过程的入参,也是存储过程的出参")])])]),t._v(" "),s("li",[t._v("流控制语句:\n"),s("ul",[s("li",[s("code",[t._v("BEGIN…END")]),t._v(":"),s("code",[t._v("BEGIN…END")]),t._v(" 中间包含了多个语句,每个语句都以("),s("code",[t._v(";")]),t._v(")号为结束符。")]),t._v(" "),s("li",[s("code",[t._v("DECLARE")]),t._v(":"),s("code",[t._v("DECLARE")]),t._v(" 用来声明变量,使用的位置在于 "),s("code",[t._v("BEGIN…END")]),t._v(" 语句中间,而且需要在其他语句使用之前进行变量的声明。")]),t._v(" "),s("li",[s("code",[t._v("SET")]),t._v(":赋值语句,用于对变量进行赋值。")]),t._v(" "),s("li",[s("code",[t._v("SELECT…INTO")]),t._v(":把从数据表中查询的结果存放到变量中,也就是为变量赋值。每次只能给一个变量赋值,不支持集合的操作。")]),t._v(" "),s("li",[s("code",[t._v("IF…THEN…ENDIF")]),t._v(":条件判断语句,可以在 "),s("code",[t._v("IF…THEN…ENDIF")]),t._v(" 中使用 "),s("code",[t._v("ELSE")]),t._v(" 和 "),s("code",[t._v("ELSEIF")]),t._v(" 来进行条件判断。")]),t._v(" "),s("li",[s("code",[t._v("CASE")]),t._v(":"),s("code",[t._v("CASE")]),t._v(" 语句用于多条件的分支判断。")])])])]),t._v(" "),s("p",[t._v("创建存储过程示例:")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DROP")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("PROCEDURE")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("IF")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("EXISTS")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token identifier"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("proc_adder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DELIMITER")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("CREATE")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DEFINER")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),s("span",{pre:!0,attrs:{class:"token identifier"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("root"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")])]),s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("@`localhost`")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("PROCEDURE")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token identifier"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("proc_adder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("IN")]),t._v(" a "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("IN")]),t._v(" b "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("OUT")]),t._v(" sum "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("BEGIN")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DECLARE")]),t._v(" c "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" a "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("is")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("null")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("then")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("set")]),t._v(" a "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("end")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" b "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("is")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("null")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("then")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("set")]),t._v(" b "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("end")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("set")]),t._v(" sum "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" a "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" b"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("END")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DELIMITER")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("p",[t._v("使用存储过程示例:")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("set")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("@b")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("call")]),t._v(" proc_adder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("@b")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("@s")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("@s")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" sum"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h3",{attrs:{id:"存储过程的利弊"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#存储过程的利弊"}},[t._v("#")]),t._v(" 存储过程的利弊")]),t._v(" "),s("p",[t._v("存储过程的优点:")]),t._v(" "),s("ul",[s("li",[s("strong",[t._v("执行效率高")]),t._v(":一次编译多次使用。")]),t._v(" "),s("li",[s("strong",[t._v("安全性强")]),t._v(":在设定存储过程的时候可以设置对用户的使用权限,这样就和视图一样具有较强的安全性。")]),t._v(" "),s("li",[s("strong",[t._v("可复用")]),t._v(":将代码封装,可以提高代码复用。")]),t._v(" "),s("li",[s("strong",[t._v("性能好")]),t._v(" "),s("ul",[s("li",[t._v("由于是预先编译,因此具有很高的性能。")]),t._v(" "),s("li",[t._v("一个存储过程替代大量 T_SQL 语句 ,可以降低网络通信量,提高通信速率。")])])])]),t._v(" "),s("p",[t._v("存储过程的缺点:")]),t._v(" "),s("ul",[s("li",[s("strong",[t._v("可移植性差")]),t._v(":存储过程不能跨数据库移植。由于不同数据库的存储过程语法几乎都不一样,十分难以维护(不通用)。")]),t._v(" "),s("li",[s("strong",[t._v("调试困难")]),t._v(":只有少数 DBMS 支持存储过程的调试。对于复杂的存储过程来说,开发和维护都不容易。")]),t._v(" "),s("li",[s("strong",[t._v("版本管理困难")]),t._v(":比如数据表索引发生变化了,可能会导致存储过程失效。我们在开发软件的时候往往需要进行版本管理,但是存储过程本身没有版本控制,版本迭代更新的时候很麻烦。")]),t._v(" "),s("li",[s("strong",[t._v("不适合高并发的场景")]),t._v(":高并发的场景需要减少数据库的压力,有时数据库会采用分库分表的方式,而且对可扩展性要求很高,在这种情况下,存储过程会变得难以维护,增加数据库的压力,显然就不适用了。")])]),t._v(" "),s("blockquote",[s("p",[s("em",[t._v("综上,存储过程的优缺点都非常突出,是否使用一定要慎重,需要根据具体应用场景来权衡")]),t._v("。")])]),t._v(" "),s("h3",{attrs:{id:"触发器"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#触发器"}},[t._v("#")]),t._v(" 触发器")]),t._v(" "),s("blockquote",[s("p",[t._v("触发器可以视为一种特殊的存储过程。")]),t._v(" "),s("p",[t._v("触发器是一种与表操作有关的数据库对象,当触发器所在表上出现指定事件时,将调用该对象,即表的操作事件触发表上的触发器的执行。")])]),t._v(" "),s("h4",{attrs:{id:"触发器特性"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#触发器特性"}},[t._v("#")]),t._v(" 触发器特性")]),t._v(" "),s("p",[t._v("可以使用触发器来进行审计跟踪,把修改记录到另外一张表中。")]),t._v(" "),s("p",[t._v("MySQL 不允许在触发器中使用 "),s("code",[t._v("CALL")]),t._v(" 语句 ,也就是不能调用存储过程。")]),t._v(" "),s("p",[s("strong",[s("code",[t._v("BEGIN")]),t._v(" 和 "),s("code",[t._v("END")])])]),t._v(" "),s("p",[t._v("当触发器的触发条件满足时,将会执行 "),s("code",[t._v("BEGIN")]),t._v(" 和 "),s("code",[t._v("END")]),t._v(" 之间的触发器执行动作。")]),t._v(" "),s("blockquote",[s("p",[t._v("🔔 注意:在 MySQL 中,分号 "),s("code",[t._v(";")]),t._v(" 是语句结束的标识符,遇到分号表示该段语句已经结束,MySQL 可以开始执行了。因此,解释器遇到触发器执行动作中的分号后就开始执行,然后会报错,因为没有找到和 BEGIN 匹配的 END。")]),t._v(" "),s("p",[t._v("这时就会用到 "),s("code",[t._v("DELIMITER")]),t._v(" 命令("),s("code",[t._v("DELIMITER")]),t._v(" 是定界符,分隔符的意思)。它是一条命令,不需要语句结束标识,语法为:"),s("code",[t._v("DELIMITER new_delemiter")]),t._v("。"),s("code",[t._v("new_delemiter")]),t._v(" 可以设为 1 个或多个长度的符号,默认的是分号 "),s("code",[t._v(";")]),t._v(",我们可以把它修改为其他符号,如 "),s("code",[t._v("$")]),t._v(" - "),s("code",[t._v("DELIMITER $")]),t._v(" 。在这之后的语句,以分号结束,解释器不会有什么反应,只有遇到了 "),s("code",[t._v("$")]),t._v(",才认为是语句结束。注意,使用完之后,我们还应该记得把它给修改回来。")])]),t._v(" "),s("p",[s("strong",[s("code",[t._v("NEW")]),t._v(" 和 "),s("code",[t._v("OLD")])])]),t._v(" "),s("ul",[s("li",[t._v("MySQL 中定义了 "),s("code",[t._v("NEW")]),t._v(" 和 "),s("code",[t._v("OLD")]),t._v(" 关键字,用来表示触发器的所在表中,触发了触发器的那一行数据。")]),t._v(" "),s("li",[t._v("在 "),s("code",[t._v("INSERT")]),t._v(" 型触发器中,"),s("code",[t._v("NEW")]),t._v(" 用来表示将要("),s("code",[t._v("BEFORE")]),t._v(")或已经("),s("code",[t._v("AFTER")]),t._v(")插入的新数据;")]),t._v(" "),s("li",[t._v("在 "),s("code",[t._v("UPDATE")]),t._v(" 型触发器中,"),s("code",[t._v("OLD")]),t._v(" 用来表示将要或已经被修改的原数据,"),s("code",[t._v("NEW")]),t._v(" 用来表示将要或已经修改为的新数据;")]),t._v(" "),s("li",[t._v("在 "),s("code",[t._v("DELETE")]),t._v(" 型触发器中,"),s("code",[t._v("OLD")]),t._v(" 用来表示将要或已经被删除的原数据;")]),t._v(" "),s("li",[t._v("使用方法: "),s("code",[t._v("NEW.columnName")]),t._v(" (columnName 为相应数据表某一列名)")])]),t._v(" "),s("h4",{attrs:{id:"触发器指令"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#触发器指令"}},[t._v("#")]),t._v(" 触发器指令")]),t._v(" "),s("blockquote",[s("p",[t._v("提示:为了理解触发器的要点,有必要先了解一下创建触发器的指令。")])]),t._v(" "),s("p",[s("code",[t._v("CREATE TRIGGER")]),t._v(" 指令用于创建触发器。")]),t._v(" "),s("p",[t._v("语法:")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("CREATE")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("TRIGGER")]),t._v(" trigger_name\ntrigger_time\ntrigger_event\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ON")]),t._v(" table_name\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FOR EACH ROW")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("BEGIN")]),t._v("\n trigger_statements\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("END")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("p",[t._v("说明:")]),t._v(" "),s("ul",[s("li",[t._v("trigger_name:触发器名")]),t._v(" "),s("li",[t._v("trigger_time: 触发器的触发时机。取值为 "),s("code",[t._v("BEFORE")]),t._v(" 或 "),s("code",[t._v("AFTER")]),t._v("。")]),t._v(" "),s("li",[t._v("trigger_event: 触发器的监听事件。取值为 "),s("code",[t._v("INSERT")]),t._v("、"),s("code",[t._v("UPDATE")]),t._v(" 或 "),s("code",[t._v("DELETE")]),t._v("。")]),t._v(" "),s("li",[t._v("table_name: 触发器的监听目标。指定在哪张表上建立触发器。")]),t._v(" "),s("li",[t._v("FOR EACH ROW: 行级监视,Mysql 固定写法,其他 DBMS 不同。")]),t._v(" "),s("li",[t._v("trigger_statements: 触发器执行动作。是一条或多条 SQL 语句的列表,列表内的每条语句都必须用分号 "),s("code",[t._v(";")]),t._v(" 来结尾。")])]),t._v(" "),s("p",[t._v("创建触发器示例:")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DELIMITER")]),t._v(" $\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("CREATE")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("TRIGGER")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token identifier"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("trigger_insert_user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")])]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("AFTER")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INSERT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ON")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token identifier"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")])]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FOR EACH ROW")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("BEGIN")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INSERT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INTO")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token identifier"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("user_history"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("user_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" operate_type"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" operate_time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("VALUES")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("NEW"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'add a user'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("now")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("END")]),t._v(" $\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DELIMITER")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("p",[t._v("查看触发器示例:")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SHOW")]),t._v(" TRIGGERS"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("p",[t._v("删除触发器示例:")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DROP")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("TRIGGER")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("IF")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("EXISTS")]),t._v(" trigger_insert_user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h2",{attrs:{id:"游标"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#游标"}},[t._v("#")]),t._v(" 游标")]),t._v(" "),s("blockquote",[s("p",[t._v("游标(CURSOR)是一个存储在 DBMS 服务器上的数据库查询,它不是一条 "),s("code",[t._v("SELECT")]),t._v(" 语句,而是被该语句检索出来的结果集。在存储过程中使用游标可以对一个结果集进行移动遍历。")])]),t._v(" "),s("p",[t._v("游标主要用于交互式应用,其中用户需要对数据集中的任意行进行浏览和修改。")]),t._v(" "),s("p",[t._v("使用游标的步骤:")]),t._v(" "),s("ol",[s("li",[s("strong",[t._v("定义游标")]),t._v(":通过 "),s("code",[t._v("DECLARE cursor_name CURSOR FOR <语句>")]),t._v(" 定义游标。这个过程没有实际检索出数据。")]),t._v(" "),s("li",[s("strong",[t._v("打开游标")]),t._v(":通过 "),s("code",[t._v("OPEN cursor_name")]),t._v(" 打开游标。")]),t._v(" "),s("li",[s("strong",[t._v("取出数据")]),t._v(":通过 "),s("code",[t._v("FETCH cursor_name INTO var_name ...")]),t._v(" 获取数据。")]),t._v(" "),s("li",[s("strong",[t._v("关闭游标")]),t._v(":通过 "),s("code",[t._v("CLOSE cursor_name")]),t._v(" 关闭游标。")]),t._v(" "),s("li",[s("strong",[t._v("释放游标")]),t._v(":通过 "),s("code",[t._v("DEALLOCATE PREPARE")]),t._v(" 释放游标。")])]),t._v(" "),s("p",[t._v("游标使用示例:")]),t._v(" "),s("div",{staticClass:"language-sql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DELIMITER")]),t._v(" $\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("CREATE")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("PROCEDURE")]),t._v(" getTotal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("BEGIN")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DECLARE")]),t._v(" total "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INT")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- 创建接收游标数据的变量")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DECLARE")]),t._v(" sid "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INT")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DECLARE")]),t._v(" sname "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("VARCHAR")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- 创建总数变量")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DECLARE")]),t._v(" sage "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INT")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- 创建结束标志变量")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DECLARE")]),t._v(" done "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DEFAULT")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- 创建游标")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DECLARE")]),t._v(" cur "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("CURSOR")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FOR")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("age "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" cursor_table "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v(" age"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("30")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- 指定游标循环结束时的返回值")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DECLARE")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("CONTINUE")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("HANDLER")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FOR")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("NOT")]),t._v(" FOUND "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SET")]),t._v(" done "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SET")]),t._v(" total "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("OPEN")]),t._v(" cur"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FETCH")]),t._v(" cur "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INTO")]),t._v(" sid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" sname"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" sage"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHILE")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("NOT")]),t._v(" done"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DO")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SET")]),t._v(" total "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" total "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("FETCH")]),t._v(" cur "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INTO")]),t._v(" sid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" sname"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" sage"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("END")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("WHILE")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("CLOSE")]),t._v(" cur"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("SELECT")]),t._v(" total"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("END")]),t._v(" $\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("DELIMITER")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- 调用存储过程")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("call")]),t._v(" getTotal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("h2",{attrs:{id:"参考资料"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#参考资料"}},[t._v("#")]),t._v(" 参考资料")]),t._v(" "),s("ul",[s("li",[s("a",{attrs:{href:"https://book.douban.com/subject/35167240/",target:"_blank",rel:"noopener noreferrer"}},[t._v("《SQL 必知必会》"),s("OutboundLink")],1)]),t._v(" "),s("li",[s("a",{attrs:{href:"https://draveness.me/mysql-transaction",target:"_blank",rel:"noopener noreferrer"}},[t._v("『浅入深出』MySQL 中事务的实现"),s("OutboundLink")],1)]),t._v(" "),s("li",[s("a",{attrs:{href:"https://www.cnblogs.com/CraryPrimitiveMan/p/4206942.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("MySQL 的学习--触发器"),s("OutboundLink")],1)]),t._v(" "),s("li",[s("a",{attrs:{href:"https://zh.wikipedia.org/wiki/SQL",target:"_blank",rel:"noopener noreferrer"}},[t._v("维基百科词条 - SQL"),s("OutboundLink")],1)]),t._v(" "),s("li",[s("a",{attrs:{href:"https://www.sitesbay.com/sql/index",target:"_blank",rel:"noopener noreferrer"}},[t._v("https://www.sitesbay.com/sql/index"),s("OutboundLink")],1)]),t._v(" "),s("li",[s("a",{attrs:{href:"https://www.w3resource.com/sql/subqueries/understanding-sql-subqueries.php",target:"_blank",rel:"noopener noreferrer"}},[t._v("SQL Subqueries"),s("OutboundLink")],1)]),t._v(" "),s("li",[s("a",{attrs:{href:"https://stackoverflow.com/questions/6294778/mysql-quick-breakdown-of-the-types-of-joins",target:"_blank",rel:"noopener noreferrer"}},[t._v("Quick breakdown of the types of joins"),s("OutboundLink")],1)]),t._v(" "),s("li",[s("a",{attrs:{href:"https://www.w3resource.com/sql/sql-union.php",target:"_blank",rel:"noopener noreferrer"}},[t._v("SQL UNION"),s("OutboundLink")],1)]),t._v(" "),s("li",[s("a",{attrs:{href:"https://www.w3resource.com/sql/database-security/create-users.php",target:"_blank",rel:"noopener noreferrer"}},[t._v("SQL database security"),s("OutboundLink")],1)]),t._v(" "),s("li",[s("a",{attrs:{href:"https://www.cnblogs.com/chenpi/p/5136483.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mysql 中的存储过程"),s("OutboundLink")],1)])])])}),[],!1,null,null,null);s.default=n.exports}}]);
\ No newline at end of file
diff --git a/assets/js/15.c2e48c7a.js b/assets/js/15.c2e48c7a.js
new file mode 100644
index 00000000..2a4744ff
--- /dev/null
+++ b/assets/js/15.c2e48c7a.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[15],{352:function(s,t,a){"use strict";a.r(t);var r=a(4),e=Object(r.a)({},(function(){var s=this,t=s._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":s.$parent.slotKey}},[t("h1",{attrs:{id:"扩展-sql"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#扩展-sql"}},[s._v("#")]),s._v(" 扩展 SQL")]),s._v(" "),t("h2",{attrs:{id:"数据库"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#数据库"}},[s._v("#")]),s._v(" 数据库")]),s._v(" "),t("h2",{attrs:{id:"表"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#表"}},[s._v("#")]),s._v(" 表")]),s._v(" "),t("h3",{attrs:{id:"查看表的基本信息"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#查看表的基本信息"}},[s._v("#")]),s._v(" 查看表的基本信息")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("*")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" information_schema"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("tables")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" table_schema "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'test'")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("AND")]),s._v(" table_name "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'user'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h3",{attrs:{id:"查看表的列信息"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#查看表的列信息"}},[s._v("#")]),s._v(" 查看表的列信息")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SELECT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("*")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("FROM")]),s._v(" information_schema"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(".")]),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("columns")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("WHERE")]),s._v(" table_schema "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'test'")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("AND")]),s._v(" table_name "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("=")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[s._v("'user'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h3",{attrs:{id:"如何批量删除大量数据"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#如何批量删除大量数据"}},[s._v("#")]),s._v(" 如何批量删除大量数据")]),s._v(" "),t("p",[s._v("如果要根据时间范围批量删除大量数据,最简单的语句如下:")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("delete")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("from")]),s._v(" orders\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("where")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("timestamp")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("<")]),s._v(" SUBDATE"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("CURDATE"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("INTERVAL")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("3")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("month")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("p",[s._v("上面的语句,大概率执行会报错,提示删除失败,因为需要删除的数据量太大了,所以需要分批删除。")]),s._v(" "),t("p",[s._v("可以先通过一次查询,找到符合条件的历史订单中最大的那个订单 ID,然后在删除语句中把删除的条件转换成按主键删除。")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("select")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token function"}},[s._v("max")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("id"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("from")]),s._v(" orders\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("where")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("timestamp")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("<")]),s._v(" SUBDATE"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),s._v("CURDATE"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(",")]),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("INTERVAL")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("3")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("month")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[s._v("-- 分批删除,? 填上一条语句查到的最大 ID")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("delete")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("from")]),s._v(" orders\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("where")]),s._v(" id "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("<=")]),s._v(" ?\n"),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("order")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("by")]),s._v(" id "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("limit")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("1000")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h3",{attrs:{id:"修改表的编码格式"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#修改表的编码格式"}},[s._v("#")]),s._v(" 修改表的编码格式")]),s._v(" "),t("p",[s._v("utf8mb4 编码是 utf8 编码的超集,兼容 utf8,并且能存储 4 字节的表情字符。如果表的编码指定为 utf8,在保存 emoji 字段时会报错。")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("ALTER")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TABLE")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("<")]),s._v("tableName"),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("CONVERT")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("TO")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("CHARACTER")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("SET")]),s._v(" utf8mb4 "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("COLLATE")]),s._v(" utf8mb4_general_ci"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n")])])]),t("h2",{attrs:{id:"其他"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#其他"}},[s._v("#")]),s._v(" 其他")]),s._v(" "),t("h3",{attrs:{id:"显示哪些线程正在运行"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#显示哪些线程正在运行"}},[s._v("#")]),s._v(" 显示哪些线程正在运行")]),s._v(" "),t("div",{staticClass:"language-sql extra-class"},[t("pre",{pre:!0,attrs:{class:"language-sql"}},[t("code",[s._v("mysql"),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v(">")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("show")]),s._v(" processlist"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(";")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("+")]),t("span",{pre:!0,attrs:{class:"token comment"}},[s._v("----+-----------------+-----------------+------+---------+-------+------------------------+------------------+")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" Id "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("User")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" Host "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" db "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" Command "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("Time")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" State "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" Info "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("+")]),t("span",{pre:!0,attrs:{class:"token comment"}},[s._v("----+-----------------+-----------------+------+---------+-------+------------------------+------------------+")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("5")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" event_scheduler "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" localhost "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("NULL")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" Daemon "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("40230")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" Waiting "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("on")]),s._v(" empty queue "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("NULL")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("10")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" root "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" localhost:"),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("10120")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token boolean"}},[s._v("NULL")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" Query "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("0")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" init "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("show")]),s._v(" processlist "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("|")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("+")]),t("span",{pre:!0,attrs:{class:"token comment"}},[s._v("----+-----------------+-----------------+------+---------+-------+------------------------+------------------+")]),s._v("\n"),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("2")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("rows")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token operator"}},[s._v("in")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token keyword"}},[s._v("set")]),s._v(" "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[s._v("0.00")]),s._v(" sec"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[s._v(")")]),s._v("\n")])])]),t("p",[s._v("Mysql 连接完成后,如果你没有后续的动作,这个连接就处于空闲状态,你可以在 "),t("code",[s._v("show processlist")]),s._v(" 命令中看到它。其中的 Command 列显示为“Sleep”的这一行,就表示现在系统里面有一个空闲连接。客户端如果太长时间没动静,连接器就会自动将它断开。这个时间是由参数 wait_timeout 控制的,默认值是 8 小时。")]),s._v(" "),t("h2",{attrs:{id:"参考资料"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#参考资料"}},[s._v("#")]),s._v(" 参考资料")]),s._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://book.douban.com/subject/35167240/",target:"_blank",rel:"noopener noreferrer"}},[s._v("《SQL 必知必会》"),t("OutboundLink")],1)])])])}),[],!1,null,null,null);t.default=e.exports}}]);
\ No newline at end of file
diff --git a/assets/js/16.b3f19b44.js b/assets/js/16.b3f19b44.js
new file mode 100644
index 00000000..daa205c7
--- /dev/null
+++ b/assets/js/16.b3f19b44.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{353:function(_,v,e){"use strict";e.r(v);var a=e(4),o=Object(a.a)({},(function(){var _=this,v=_._self._c;return v("ContentSlotsDistributor",{attrs:{"slot-key":_.$parent.slotKey}},[v("h1",{attrs:{id:"sql-cheat-sheet"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#sql-cheat-sheet"}},[_._v("#")]),_._v(" SQL Cheat Sheet")]),_._v(" "),v("h2",{attrs:{id:"查找数据的查询"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#查找数据的查询"}},[_._v("#")]),_._v(" 查找数据的查询")]),_._v(" "),v("h3",{attrs:{id:"select-用于从数据库中选择数据"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#select-用于从数据库中选择数据"}},[_._v("#")]),_._v(" "),v("strong",[_._v("SELECT")]),_._v(": 用于从数据库中选择数据")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" table_name;")])]),_._v(" "),v("h3",{attrs:{id:"distinct-用于过滤掉重复的值并返回指定列的行"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#distinct-用于过滤掉重复的值并返回指定列的行"}},[_._v("#")]),_._v(" "),v("strong",[_._v("DISTINCT")]),_._v(": 用于过滤掉重复的值并返回指定列的行")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT DISTINCT")]),_._v(" column_name;")])]),_._v(" "),v("h3",{attrs:{id:"where-用于过滤记录-行"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#where-用于过滤记录-行"}},[_._v("#")]),_._v(" "),v("strong",[_._v("WHERE")]),_._v(": 用于过滤记录/行")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT")]),_._v(" column1, column2 "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition;")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition1 "),v("code",[_._v("AND")]),_._v(" condition2;")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition1 "),v("code",[_._v("OR")]),_._v(" condition2;")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE NOT")]),_._v(" condition;")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition1 "),v("code",[_._v("AND")]),_._v(" (condition2 "),v("code",[_._v("OR")]),_._v(" condition3);")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE EXISTS")]),_._v(" ("),v("code",[_._v("SELECT")]),_._v(" column_name "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition);")])]),_._v(" "),v("h3",{attrs:{id:"order-by-用于结果集的排序-升序-asc-或者降序-desc"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#order-by-用于结果集的排序-升序-asc-或者降序-desc"}},[_._v("#")]),_._v(" "),v("strong",[_._v("ORDER BY")]),_._v(": 用于结果集的排序,升序(ASC)或者降序(DESC)")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("ORDER BY")]),_._v(" column;")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("ORDER BY")]),_._v(" column "),v("code",[_._v("DESC")]),_._v(";")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("ORDER BY")]),_._v(" column1 "),v("code",[_._v("ASC")]),_._v(", column2 "),v("code",[_._v("DESC")]),_._v(";")])]),_._v(" "),v("h3",{attrs:{id:"select-top-用于指定从表顶部返回的记录数"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#select-top-用于指定从表顶部返回的记录数"}},[_._v("#")]),_._v(" "),v("strong",[_._v("SELECT TOP")]),_._v(": 用于指定从表顶部返回的记录数")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT TOP")]),_._v(" number columns_names "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition;")]),_._v(" "),v("li",[v("code",[_._v("SELECT TOP")]),_._v(" percent columns_names "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition;")]),_._v(" "),v("li",[_._v("并非所有数据库系统都支持"),v("code",[_._v("SELECT TOP")]),_._v("。 MySQL 中是"),v("code",[_._v("LIMIT")]),_._v("子句")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" column_names "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("LIMIT")]),_._v(" offset, count;")])]),_._v(" "),v("h3",{attrs:{id:"like-用于搜索列中的特定模式-where-子句中使用的运算符"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#like-用于搜索列中的特定模式-where-子句中使用的运算符"}},[_._v("#")]),_._v(" "),v("strong",[_._v("LIKE")]),_._v(": 用于搜索列中的特定模式,WHERE 子句中使用的运算符")]),_._v(" "),v("ul",[v("li",[_._v("% (percent sign) 是一个表示零个,一个或多个字符的通配符")]),_._v(" "),v("li",[_._v("_ (underscore) 是一个表示单个字符通配符")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" column_names "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" column_name "),v("code",[_._v("LIKE")]),_._v(" pattern;")]),_._v(" "),v("li",[v("code",[_._v("LIKE")]),_._v(" ‘a%’ (查找任何以“a”开头的值)")]),_._v(" "),v("li",[v("code",[_._v("LIKE")]),_._v(" ‘%a’ (查找任何以“a”结尾的值)")]),_._v(" "),v("li",[v("code",[_._v("LIKE")]),_._v(" ‘%or%’ (查找任何包含“or”的值)")]),_._v(" "),v("li",[v("code",[_._v("LIKE")]),_._v(" ‘_r%’ (查找任何第二位是“r”的值)")]),_._v(" "),v("li",[v("code",[_._v("LIKE")]),_._v(" ‘a*%*%’ (查找任何以“a”开头且长度至少为 3 的值)")]),_._v(" "),v("li",[v("code",[_._v("LIKE")]),_._v(" ‘[a-c]%’(查找任何以“a”或“b”或“c”开头的值)")])]),_._v(" "),v("h3",{attrs:{id:"in-用于在-where-子句中指定多个值的运算符"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#in-用于在-where-子句中指定多个值的运算符"}},[_._v("#")]),_._v(" "),v("strong",[_._v("IN")]),_._v(": 用于在 WHERE 子句中指定多个值的运算符")]),_._v(" "),v("ul",[v("li",[_._v("本质上,IN 运算符是多个 OR 条件的简写")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" column_names "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" column_name "),v("code",[_._v("IN")]),_._v(" (value1, value2, …);")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" column_names "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" column_name "),v("code",[_._v("IN")]),_._v(" ("),v("code",[_._v("SELECT STATEMENT")]),_._v(");")])]),_._v(" "),v("h3",{attrs:{id:"between-用于过滤给定范围的值的运算符"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#between-用于过滤给定范围的值的运算符"}},[_._v("#")]),_._v(" "),v("strong",[_._v("BETWEEN")]),_._v(": 用于过滤给定范围的值的运算符")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT")]),_._v(" column_names "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" column_name "),v("code",[_._v("BETWEEN")]),_._v(" value1 "),v("code",[_._v("AND")]),_._v(" value2;")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" Products "),v("code",[_._v("WHERE")]),_._v(" (column_name "),v("code",[_._v("BETWEEN")]),_._v(" value1 "),v("code",[_._v("AND")]),_._v(" value2) "),v("code",[_._v("AND NOT")]),_._v(" column_name2 "),v("code",[_._v("IN")]),_._v(" (value3, value4);")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" Products "),v("code",[_._v("WHERE")]),_._v(" column_name "),v("code",[_._v("BETWEEN")]),_._v(" #01/07/1999# AND #03/12/1999#;")])]),_._v(" "),v("h3",{attrs:{id:"null-代表一个字段没有值"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#null-代表一个字段没有值"}},[_._v("#")]),_._v(" "),v("strong",[_._v("NULL")]),_._v(": 代表一个字段没有值")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" column_name "),v("code",[_._v("IS NULL")]),_._v(";")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" column_name "),v("code",[_._v("IS NOT NULL")]),_._v(";")])]),_._v(" "),v("h3",{attrs:{id:"as-用于给表或者列分配别名"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#as-用于给表或者列分配别名"}},[_._v("#")]),_._v(" "),v("strong",[_._v("AS")]),_._v(": 用于给表或者列分配别名")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT")]),_._v(" column_name "),v("code",[_._v("AS")]),_._v(" alias_name "),v("code",[_._v("FROM")]),_._v(" table_name;")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" column_name "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("AS")]),_._v(" alias_name;")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" column_name "),v("code",[_._v("AS")]),_._v(" alias_name1, column_name2 "),v("code",[_._v("AS")]),_._v(" alias_name2;")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" column_name1, column_name2 + ‘, ‘ + column_name3 "),v("code",[_._v("AS")]),_._v(" alias_name;")])]),_._v(" "),v("h3",{attrs:{id:"union-用于组合两个或者多个-select-语句的结果集的运算符"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#union-用于组合两个或者多个-select-语句的结果集的运算符"}},[_._v("#")]),_._v(" "),v("strong",[_._v("UNION")]),_._v(": 用于组合两个或者多个 SELECT 语句的结果集的运算符")]),_._v(" "),v("ul",[v("li",[_._v("每个 SELECT 语句必须拥有相同的列数")]),_._v(" "),v("li",[_._v("列必须拥有相似的数据类型")]),_._v(" "),v("li",[_._v("每个 SELECT 语句中的列也必须具有相同的顺序")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" columns_names "),v("code",[_._v("FROM")]),_._v(" table1 "),v("code",[_._v("UNION SELECT")]),_._v(" column_name "),v("code",[_._v("FROM")]),_._v(" table2;")]),_._v(" "),v("li",[v("code",[_._v("UNION")]),_._v(" 仅允许选择不同的值, "),v("code",[_._v("UNION ALL")]),_._v(" 允许重复")])]),_._v(" "),v("h3",{attrs:{id:"any-all-用于检查-where-或-having-子句中使用的子查询条件的运算符"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#any-all-用于检查-where-或-having-子句中使用的子查询条件的运算符"}},[_._v("#")]),_._v(" "),v("strong",[_._v("ANY|ALL")]),_._v(": 用于检查 WHERE 或 HAVING 子句中使用的子查询条件的运算符")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("ANY")]),_._v(" 如果任何子查询值满足条件,则返回 true。")]),_._v(" "),v("li",[v("code",[_._v("ALL")]),_._v(" 如果所有子查询值都满足条件,则返回 true。")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" columns_names "),v("code",[_._v("FROM")]),_._v(" table1 "),v("code",[_._v("WHERE")]),_._v(" column_name operator ("),v("code",[_._v("ANY")]),_._v("|"),v("code",[_._v("ALL")]),_._v(") ("),v("code",[_._v("SELECT")]),_._v(" column_name "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition);")])]),_._v(" "),v("h3",{attrs:{id:"group-by-通常与聚合函数-count-max-min-sum-avg-一起使用-用于将结果集分组为一列或多列"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#group-by-通常与聚合函数-count-max-min-sum-avg-一起使用-用于将结果集分组为一列或多列"}},[_._v("#")]),_._v(" "),v("strong",[_._v("GROUP BY")]),_._v(": 通常与聚合函数(COUNT,MAX,MIN,SUM,AVG)一起使用,用于将结果集分组为一列或多列")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT")]),_._v(" column_name1, COUNT(column_name2) "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition "),v("code",[_._v("GROUP BY")]),_._v(" column_name1 "),v("code",[_._v("ORDER BY")]),_._v(" COUNT(column_name2) DESC;")])]),_._v(" "),v("h3",{attrs:{id:"having-having-子句指定-select-语句应仅返回聚合值满足指定条件的行。它被添加到-sql-语言中-因为-where-关键字不能与聚合函数一起使用。"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#having-having-子句指定-select-语句应仅返回聚合值满足指定条件的行。它被添加到-sql-语言中-因为-where-关键字不能与聚合函数一起使用。"}},[_._v("#")]),_._v(" "),v("strong",[_._v("HAVING")]),_._v(": HAVING 子句指定 SELECT 语句应仅返回聚合值满足指定条件的行。它被添加到 SQL 语言中,因为 WHERE 关键字不能与聚合函数一起使用。")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT")]),_._v(" "),v("code",[_._v("COUNT")]),_._v("(column_name1), column_name2 "),v("code",[_._v("FROM")]),_._v(" table "),v("code",[_._v("GROUP BY")]),_._v(" column_name2 "),v("code",[_._v("HAVING")]),_._v(" "),v("code",[_._v("COUNT(")]),_._v("column_name1"),v("code",[_._v(")")]),_._v(" > 5;")])]),_._v(" "),v("h2",{attrs:{id:"修改数据的查询"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#修改数据的查询"}},[_._v("#")]),_._v(" 修改数据的查询")]),_._v(" "),v("h3",{attrs:{id:"insert-into-用于在表中插入新记录-行"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#insert-into-用于在表中插入新记录-行"}},[_._v("#")]),_._v(" "),v("strong",[_._v("INSERT INTO")]),_._v(": 用于在表中插入新记录/行")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("INSERT INTO")]),_._v(" table_name (column1, column2) "),v("code",[_._v("VALUES")]),_._v(" (value1, value2);")]),_._v(" "),v("li",[v("code",[_._v("INSERT INTO")]),_._v(" table_name "),v("code",[_._v("VALUES")]),_._v(" (value1, value2 …);")])]),_._v(" "),v("h3",{attrs:{id:"update-用于修改表中的现有记录-行"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#update-用于修改表中的现有记录-行"}},[_._v("#")]),_._v(" "),v("strong",[_._v("UPDATE")]),_._v(": 用于修改表中的现有记录/行")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("UPDATE")]),_._v(" table_name "),v("code",[_._v("SET")]),_._v(" column1 = value1, column2 = value2 "),v("code",[_._v("WHERE")]),_._v(" condition;")]),_._v(" "),v("li",[v("code",[_._v("UPDATE")]),_._v(" table_name "),v("code",[_._v("SET")]),_._v(" column_name = value;")])]),_._v(" "),v("h3",{attrs:{id:"delete-用于删除表中的现有记录-行"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#delete-用于删除表中的现有记录-行"}},[_._v("#")]),_._v(" "),v("strong",[_._v("DELETE")]),_._v(": 用于删除表中的现有记录/行")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("DELETE FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition;")]),_._v(" "),v("li",[v("code",[_._v("DELETE")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" table_name;")])]),_._v(" "),v("h2",{attrs:{id:"聚合查询"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#聚合查询"}},[_._v("#")]),_._v(" 聚合查询")]),_._v(" "),v("h3",{attrs:{id:"count-返回出现次数"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#count-返回出现次数"}},[_._v("#")]),_._v(" "),v("strong",[_._v("COUNT")]),_._v(": 返回出现次数")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT COUNT (DISTINCT")]),_._v(" column_name"),v("code",[_._v(")")]),_._v(";")])]),_._v(" "),v("h3",{attrs:{id:"min-and-max-返回所选列的最小-最大值"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#min-and-max-返回所选列的最小-最大值"}},[_._v("#")]),_._v(" "),v("strong",[_._v("MIN() and MAX()")]),_._v(": 返回所选列的最小/最大值")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT MIN (")]),_._v("column_names"),v("code",[_._v(") FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition;")]),_._v(" "),v("li",[v("code",[_._v("SELECT MAX (")]),_._v("column_names"),v("code",[_._v(") FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition;")])]),_._v(" "),v("h3",{attrs:{id:"avg-返回数字列的平均值"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#avg-返回数字列的平均值"}},[_._v("#")]),_._v(" "),v("strong",[_._v("AVG()")]),_._v(": 返回数字列的平均值")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT AVG (")]),_._v("column_name"),v("code",[_._v(") FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition;")])]),_._v(" "),v("h3",{attrs:{id:"sum-返回数值列的总和"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#sum-返回数值列的总和"}},[_._v("#")]),_._v(" "),v("strong",[_._v("SUM()")]),_._v(": 返回数值列的总和")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT SUM (")]),_._v("column_name"),v("code",[_._v(") FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition;")])]),_._v(" "),v("h2",{attrs:{id:"连接查询"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#连接查询"}},[_._v("#")]),_._v(" 连接查询")]),_._v(" "),v("h3",{attrs:{id:"inner-join-内连接-返回在两张表中具有匹配值的记录"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#inner-join-内连接-返回在两张表中具有匹配值的记录"}},[_._v("#")]),_._v(" "),v("strong",[_._v("INNER JOIN")]),_._v(": 内连接,返回在两张表中具有匹配值的记录")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT")]),_._v(" column_names "),v("code",[_._v("FROM")]),_._v(" table1 "),v("code",[_._v("INNER JOIN")]),_._v(" table2 "),v("code",[_._v("ON")]),_._v(" table1.column_name=table2.column_name;")]),_._v(" "),v("li",[v("code",[_._v("SELECT")]),_._v(" table1.column_name1, table2.column_name2, table3.column_name3 "),v("code",[_._v("FROM")]),_._v(" ((table1 "),v("code",[_._v("INNER JOIN")]),_._v(" table2 "),v("code",[_._v("ON")]),_._v(" relationship) "),v("code",[_._v("INNER JOIN")]),_._v(" table3 "),v("code",[_._v("ON")]),_._v(" relationship);")])]),_._v(" "),v("h3",{attrs:{id:"left-outer-join-左外连接-返回左表-table1-中的所有记录-以及右表中的匹配记录-table2"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#left-outer-join-左外连接-返回左表-table1-中的所有记录-以及右表中的匹配记录-table2"}},[_._v("#")]),_._v(" "),v("strong",[_._v("LEFT (OUTER) JOIN")]),_._v(": 左外连接,返回左表(table1)中的所有记录,以及右表中的匹配记录(table2)")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT")]),_._v(" column_names "),v("code",[_._v("FROM")]),_._v(" table1 "),v("code",[_._v("LEFT JOIN")]),_._v(" table2 "),v("code",[_._v("ON")]),_._v(" table1.column_name=table2.column_name;")])]),_._v(" "),v("h3",{attrs:{id:"right-outer-join-右外连接-返回右表-table2-中的所有记录-以及左表-table1-中匹配的记录"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#right-outer-join-右外连接-返回右表-table2-中的所有记录-以及左表-table1-中匹配的记录"}},[_._v("#")]),_._v(" "),v("strong",[_._v("RIGHT (OUTER) JOIN")]),_._v(": 右外连接,返回右表(table2)中的所有记录,以及左表(table1)中匹配的记录")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT")]),_._v(" column_names "),v("code",[_._v("FROM")]),_._v(" table1 "),v("code",[_._v("RIGHT JOIN")]),_._v(" table2 "),v("code",[_._v("ON")]),_._v(" table1.column_name=table2.column_name;")])]),_._v(" "),v("h3",{attrs:{id:"full-outer-join-全外连接-全连接是左右外连接的并集-连接表包含被连接的表的所有记录-如果缺少匹配的记录-以-null-填充。"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#full-outer-join-全外连接-全连接是左右外连接的并集-连接表包含被连接的表的所有记录-如果缺少匹配的记录-以-null-填充。"}},[_._v("#")]),_._v(" "),v("strong",[_._v("FULL (OUTER) JOIN")]),_._v(": 全外连接,全连接是左右外连接的并集. 连接表包含被连接的表的所有记录, 如果缺少匹配的记录, 以 NULL 填充。")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT")]),_._v(" column_names "),v("code",[_._v("FROM")]),_._v(" table1 "),v("code",[_._v("FULL OUTER JOIN")]),_._v(" table2 "),v("code",[_._v("ON")]),_._v(" table1.column_name=table2.column_name;")])]),_._v(" "),v("h3",{attrs:{id:"self-join-自连接-表自身连接"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#self-join-自连接-表自身连接"}},[_._v("#")]),_._v(" "),v("strong",[_._v("Self JOIN")]),_._v(": 自连接,表自身连接")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT")]),_._v(" column_names "),v("code",[_._v("FROM")]),_._v(" table1 T1, table1 T2 "),v("code",[_._v("WHERE")]),_._v(" condition;")])]),_._v(" "),v("h2",{attrs:{id:"视图查询"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#视图查询"}},[_._v("#")]),_._v(" 视图查询")]),_._v(" "),v("h3",{attrs:{id:"create-创建视图"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#create-创建视图"}},[_._v("#")]),_._v(" "),v("strong",[_._v("CREATE")]),_._v(": 创建视图")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("CREATE VIEW")]),_._v(" view_name "),v("code",[_._v("AS SELECT")]),_._v(" column1, column2 "),v("code",[_._v("FROM")]),_._v(" table_name "),v("code",[_._v("WHERE")]),_._v(" condition;")])]),_._v(" "),v("h3",{attrs:{id:"select-检索视图"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#select-检索视图"}},[_._v("#")]),_._v(" "),v("strong",[_._v("SELECT")]),_._v(": 检索视图")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("SELECT")]),_._v(" * "),v("code",[_._v("FROM")]),_._v(" view_name;")])]),_._v(" "),v("h3",{attrs:{id:"drop-删除视图"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#drop-删除视图"}},[_._v("#")]),_._v(" "),v("strong",[_._v("DROP")]),_._v(": 删除视图")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("DROP VIEW")]),_._v(" view_name;")])]),_._v(" "),v("h2",{attrs:{id:"修改表的查询"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#修改表的查询"}},[_._v("#")]),_._v(" 修改表的查询")]),_._v(" "),v("h3",{attrs:{id:"add-添加字段"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#add-添加字段"}},[_._v("#")]),_._v(" "),v("strong",[_._v("ADD")]),_._v(": 添加字段")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("ALTER TABLE")]),_._v(" table_name "),v("code",[_._v("ADD")]),_._v(" column_name column_definition;")])]),_._v(" "),v("h3",{attrs:{id:"modify-修改字段数据类型"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#modify-修改字段数据类型"}},[_._v("#")]),_._v(" "),v("strong",[_._v("MODIFY")]),_._v(": 修改字段数据类型")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("ALTER TABLE")]),_._v(" table_name "),v("code",[_._v("MODIFY")]),_._v(" column_name column_type;")])]),_._v(" "),v("h3",{attrs:{id:"drop-删除字段"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#drop-删除字段"}},[_._v("#")]),_._v(" "),v("strong",[_._v("DROP")]),_._v(": 删除字段")]),_._v(" "),v("ul",[v("li",[v("code",[_._v("ALTER TABLE")]),_._v(" table_name "),v("code",[_._v("DROP COLUMN")]),_._v(" column_name;")])])])}),[],!1,null,null,null);v.default=o.exports}}]);
\ No newline at end of file
diff --git a/assets/js/17.afee0370.js b/assets/js/17.afee0370.js
new file mode 100644
index 00000000..002591e3
--- /dev/null
+++ b/assets/js/17.afee0370.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[17],{354:function(t,r,e){"use strict";e.r(r);var a=e(4),s=Object(a.a)({},(function(){var t=this,r=t._self._c;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h1",{attrs:{id:"关系型数据库综合知识"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#关系型数据库综合知识"}},[t._v("#")]),t._v(" 关系型数据库综合知识")]),t._v(" "),r("h2",{attrs:{id:"📖-内容"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#📖-内容"}},[t._v("#")]),t._v(" 📖 内容")]),t._v(" "),r("h3",{attrs:{id:"关系型数据库面试总结-💯"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#关系型数据库面试总结-💯"}},[t._v("#")]),t._v(" "),r("RouterLink",{attrs:{to:"/12.数据库/03.关系型数据库/01.综合/01.关系型数据库面试.html"}},[t._v("关系型数据库面试总结")]),t._v(" 💯")],1),t._v(" "),r("h3",{attrs:{id:"sql-语法基础特性"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#sql-语法基础特性"}},[t._v("#")]),t._v(" "),r("RouterLink",{attrs:{to:"/12.数据库/03.关系型数据库/01.综合/02.SQL语法基础特性.html"}},[t._v("SQL 语法基础特性")])],1),t._v(" "),r("h3",{attrs:{id:"sql-语法高级特性"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#sql-语法高级特性"}},[t._v("#")]),t._v(" "),r("RouterLink",{attrs:{to:"/12.数据库/03.关系型数据库/01.综合/03.SQL语法高级特性.html"}},[t._v("SQL 语法高级特性")])],1),t._v(" "),r("h3",{attrs:{id:"扩展-sql"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#扩展-sql"}},[t._v("#")]),t._v(" "),r("RouterLink",{attrs:{to:"/12.数据库/03.关系型数据库/01.综合/03.扩展SQL.html"}},[t._v("扩展 SQL")])],1),t._v(" "),r("h3",{attrs:{id:"sql-cheat-sheet"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#sql-cheat-sheet"}},[t._v("#")]),t._v(" "),r("RouterLink",{attrs:{to:"/12.数据库/03.关系型数据库/01.综合/99.SqlCheatSheet.html"}},[t._v("SQL Cheat Sheet")])],1),t._v(" "),r("h2",{attrs:{id:"📚-资料"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#📚-资料"}},[t._v("#")]),t._v(" 📚 资料")]),t._v(" "),r("ul",[r("li",[r("strong",[t._v("官方")]),t._v(" "),r("ul",[r("li",[r("a",{attrs:{href:"https://www.mysql.com/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mysql 官网"),r("OutboundLink")],1)]),t._v(" "),r("li",[r("a",{attrs:{href:"https://dev.mysql.com/doc/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mysql 官方文档"),r("OutboundLink")],1)]),t._v(" "),r("li",[r("a",{attrs:{href:"https://dev.mysql.com/doc/refman/8.0/en/mysql.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mysql 官方文档之命令行客户端"),r("OutboundLink")],1)])])]),t._v(" "),r("li",[r("strong",[t._v("书籍")]),t._v(" "),r("ul",[r("li",[r("a",{attrs:{href:"https://item.jd.com/11220393.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("《高性能 MySQL》"),r("OutboundLink")],1),t._v(" - Mysql 经典")]),t._v(" "),r("li",[r("a",{attrs:{href:"https://book.douban.com/subject/35167240/",target:"_blank",rel:"noopener noreferrer"}},[t._v("《SQL 必知必会》"),r("OutboundLink")],1),t._v(" - SQL 入门")])])]),t._v(" "),r("li",[r("strong",[t._v("教程")]),t._v(" "),r("ul",[r("li",[r("a",{attrs:{href:"http://www.runoob.com/mymysql-tutorial.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("runoob.com MySQL 教程"),r("OutboundLink")],1),t._v(" - 入门级 SQL 教程")]),t._v(" "),r("li",[r("a",{attrs:{href:"https://github.com/jaywcjlove/mysql-tutorial",target:"_blank",rel:"noopener noreferrer"}},[t._v("mysql-tutorial"),r("OutboundLink")],1)])])]),t._v(" "),r("li",[r("strong",[t._v("更多资源")]),t._v(" "),r("ul",[r("li",[r("a",{attrs:{href:"https://github.com/jobbole/awesome-mysql-cn",target:"_blank",rel:"noopener noreferrer"}},[t._v("awesome-mysql"),r("OutboundLink")],1)])])])]),t._v(" "),r("h2",{attrs:{id:"🚪-传送"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#🚪-传送"}},[t._v("#")]),t._v(" 🚪 传送")]),t._v(" "),r("p",[t._v("◾ 💧 "),r("a",{attrs:{href:"https://dunwu.github.io/waterdrop/",target:"_blank",rel:"noopener noreferrer"}},[t._v("钝悟的 IT 知识图谱"),r("OutboundLink")],1),t._v(" ◾ 🎯 "),r("a",{attrs:{href:"https://dunwu.github.io/blog/",target:"_blank",rel:"noopener noreferrer"}},[t._v("钝悟的博客"),r("OutboundLink")],1),t._v(" ◾")])])}),[],!1,null,null,null);r.default=s.exports}}]);
\ No newline at end of file
diff --git a/assets/js/18.0eb469ef.js b/assets/js/18.0eb469ef.js
new file mode 100644
index 00000000..e87b2ace
--- /dev/null
+++ b/assets/js/18.0eb469ef.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[18],{355:function(t,a,s){"use strict";s.r(a);var r=s(4),e=Object(r.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"mysql-应用指南"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#mysql-应用指南"}},[t._v("#")]),t._v(" Mysql 应用指南")]),t._v(" "),a("h2",{attrs:{id:"sql-执行过程"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#sql-执行过程"}},[t._v("#")]),t._v(" SQL 执行过程")]),t._v(" "),a("p",[t._v("学习 Mysql,最好是先从宏观上了解 Mysql 工作原理。")]),t._v(" "),a("blockquote",[a("p",[t._v("参考:"),a("RouterLink",{attrs:{to:"/12.数据库/03.关系型数据库/02.Mysql/02.MySQL工作流.html"}},[t._v("Mysql 工作流")])],1)]),t._v(" "),a("h2",{attrs:{id:"存储引擎"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#存储引擎"}},[t._v("#")]),t._v(" 存储引擎")]),t._v(" "),a("p",[t._v("在文件系统中,Mysql 将每个数据库(也可以成为 schema)保存为数据目录下的一个子目录。创建表示,Mysql 会在数据库子目录下创建一个和表同名的 "),a("code",[t._v(".frm")]),t._v(" 文件保存表的定义。因为 Mysql 使用文件系统的目录和文件来保存数据库和表的定义,大小写敏感性和具体平台密切相关。Windows 中大小写不敏感;类 Unix 中大小写敏感。"),a("strong",[t._v("不同的存储引擎保存数据和索引的方式是不同的,但表的定义则是在 Mysql 服务层统一处理的。")])]),t._v(" "),a("h3",{attrs:{id:"选择存储引擎"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#选择存储引擎"}},[t._v("#")]),t._v(" 选择存储引擎")]),t._v(" "),a("h4",{attrs:{id:"mysql-内置的存储引擎"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#mysql-内置的存储引擎"}},[t._v("#")]),t._v(" Mysql 内置的存储引擎")]),t._v(" "),a("div",{staticClass:"language-shell extra-class"},[a("pre",{pre:!0,attrs:{class:"language-shell"}},[a("code",[t._v("mysql"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" SHOW ENGINES"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" Engine "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" Support "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" Comment "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" Transactions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" XA "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" Savepoints "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" FEDERATED "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" Federated MySQL storage engine "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NULL "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NULL "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NULL "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" MEMORY "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" YES "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" Hash based, stored "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" memory, useful "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" temporary tables "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" InnoDB "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" DEFAULT "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" Supports transactions, row-level locking, and foreign keys "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" YES "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" YES "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" YES "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" PERFORMANCE_SCHEMA "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" YES "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" Performance Schema "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" MyISAM "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" YES "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" MyISAM storage engine "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" MRG_MYISAM "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" YES "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" Collection of identical MyISAM tables "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" BLACKHOLE "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" YES "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" /dev/null storage engine "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("anything you "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("write")]),t._v(" to it disappears"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" CSV "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" YES "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" CSV storage engine "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ARCHIVE "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" YES "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" Archive storage engine "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" NO "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+\n"),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("9")]),t._v(" rows "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("set")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.00")]),t._v(" sec"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("ul",[a("li",[a("strong",[t._v("InnoDB")]),t._v(" - Mysql 的默认事务型存储引擎,并且提供了行级锁和外键的约束。性能不错且支持自动崩溃恢复。")]),t._v(" "),a("li",[a("strong",[t._v("MyISAM")]),t._v(" - Mysql 5.1 版本前的默认存储引擎。特性丰富但不支持事务,也不支持行级锁和外键,也没有崩溃恢复功能。")]),t._v(" "),a("li",[a("strong",[t._v("CSV")]),t._v(" - 可以将 CSV 文件作为 Mysql 的表来处理,但这种表不支持索引。")]),t._v(" "),a("li",[a("strong",[t._v("Memory")]),t._v(" - 适合快速访问数据,且数据不会被修改,重启丢失也没有关系。")]),t._v(" "),a("li",[a("strong",[t._v("NDB")]),t._v(" - 用于 Mysql 集群场景。")])]),t._v(" "),a("h4",{attrs:{id:"如何选择合适的存储引擎"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#如何选择合适的存储引擎"}},[t._v("#")]),t._v(" 如何选择合适的存储引擎")]),t._v(" "),a("p",[t._v("大多数情况下,InnoDB 都是正确的选择,除非需要用到 InnoDB 不具备的特性。")]),t._v(" "),a("p",[t._v("如果应用需要选择 InnoDB 以外的存储引擎,可以考虑以下因素:")]),t._v(" "),a("ul",[a("li",[t._v("事务:如果需要支持事务,InnoDB 是首选。如果不需要支持事务,且主要是 SELECT 和 INSERT 操作,MyISAM 是不错的选择。所以,如果 Mysql 部署方式为主备模式,并进行读写分离。那么可以这么做:主节点只支持写操作,默认引擎为 InnoDB;备节点只支持读操作,默认引擎为 MyISAM。")]),t._v(" "),a("li",[t._v("并发:MyISAM 只支持表级锁,而 InnoDB 还支持行级锁。所以,InnoDB 并发性能更高。")]),t._v(" "),a("li",[t._v("外键:InnoDB 支持外键。")]),t._v(" "),a("li",[t._v("备份:InnoDB 支持在线热备份。")]),t._v(" "),a("li",[t._v("崩溃恢复:MyISAM 崩溃后发生损坏的概率比 InnoDB 高很多,而且恢复的速度也更慢。")]),t._v(" "),a("li",[t._v("其它特性:MyISAM 支持压缩表和空间数据索引。")])]),t._v(" "),a("h4",{attrs:{id:"转换表的存储引擎"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#转换表的存储引擎"}},[t._v("#")]),t._v(" 转换表的存储引擎")]),t._v(" "),a("p",[t._v("下面的语句可以将 mytable 表的引擎修改为 InnoDB")]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ALTER")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("TABLE")]),t._v(" mytable "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("ENGINE")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("InnoDB")]),t._v("\n")])])]),a("h3",{attrs:{id:"myisam"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#myisam"}},[t._v("#")]),t._v(" MyISAM")]),t._v(" "),a("p",[t._v("MyISAM 设计简单,数据以紧密格式存储。对于只读数据,或者表比较小、可以容忍修复操作,则依然可以使用 MyISAM。")]),t._v(" "),a("p",[t._v("MyISAM 引擎使用 B+Tree 作为索引结构,"),a("strong",[t._v("叶节点的 data 域存放的是数据记录的地址")]),t._v("。")]),t._v(" "),a("p",[t._v("MyISAM 提供了大量的特性,包括:全文索引、压缩表、空间函数等。但是,MyISAM 不支持事务和行级锁。并且 MyISAM 不支持崩溃后的安全恢复。")]),t._v(" "),a("h3",{attrs:{id:"innodb"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#innodb"}},[t._v("#")]),t._v(" InnoDB")]),t._v(" "),a("p",[t._v("InnoDB 是 MySQL 默认的事务型存储引擎,只有在需要 InnoDB 不支持的特性时,才考虑使用其它存储引擎。")]),t._v(" "),a("p",[t._v("然 InnoDB 也使用 B+Tree 作为索引结构,但具体实现方式却与 MyISAM 截然不同。MyISAM 索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而"),a("strong",[t._v("在 InnoDB 中,表数据文件本身就是按 B+Tree 组织的一个索引结构")]),t._v(",这棵树的叶节点 data 域保存了完整的数据记录。这个"),a("strong",[t._v("索引的 key 是数据表的主键")]),t._v(",因此"),a("strong",[t._v("InnoDB 表数据文件本身就是主索引")]),t._v("。")]),t._v(" "),a("p",[t._v("InnoDB 采用 MVCC 来支持高并发,并且实现了四个标准的隔离级别。其默认级别是可重复读(REPEATABLE READ),并且通过间隙锁(next-key locking)防止幻读。")]),t._v(" "),a("p",[t._v("InnoDB 是基于聚簇索引建立的,与其他存储引擎有很大不同。在索引中保存了数据,从而避免直接读取磁盘,因此对查询性能有很大的提升。")]),t._v(" "),a("p",[t._v("内部做了很多优化,包括从磁盘读取数据时采用的可预测性读、能够加快读操作并且自动创建的自适应哈希索引、能够加速插入操作的插入缓冲区等。")]),t._v(" "),a("p",[t._v("支持真正的在线热备份。其它存储引擎不支持在线热备份,要获取一致性视图需要停止对所有表的写入,而在读写混合场景中,停止写入可能也意味着停止读取。")]),t._v(" "),a("h2",{attrs:{id:"数据类型"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#数据类型"}},[t._v("#")]),t._v(" 数据类型")]),t._v(" "),a("h3",{attrs:{id:"整型"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#整型"}},[t._v("#")]),t._v(" 整型")]),t._v(" "),a("p",[a("code",[t._v("TINYINT")]),t._v(", "),a("code",[t._v("SMALLINT")]),t._v(", "),a("code",[t._v("MEDIUMINT")]),t._v(", "),a("code",[t._v("INT")]),t._v(", "),a("code",[t._v("BIGINT")]),t._v(" 分别使用 "),a("code",[t._v("8")]),t._v(", "),a("code",[t._v("16")]),t._v(", "),a("code",[t._v("24")]),t._v(", "),a("code",[t._v("32")]),t._v(", "),a("code",[t._v("64")]),t._v(" 位存储空间,一般情况下越小的列越好。")]),t._v(" "),a("p",[a("strong",[a("code",[t._v("UNSIGNED")]),t._v(" 表示不允许负值,大致可以使正数的上限提高一倍")]),t._v("。")]),t._v(" "),a("p",[a("code",[t._v("INT(11)")]),t._v(" 中的数字只是规定了交互工具显示字符的个数,对于存储和计算来说是没有意义的。")]),t._v(" "),a("h3",{attrs:{id:"浮点型"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#浮点型"}},[t._v("#")]),t._v(" 浮点型")]),t._v(" "),a("p",[a("code",[t._v("FLOAT")]),t._v(" 和 "),a("code",[t._v("DOUBLE")]),t._v(" 为浮点类型。")]),t._v(" "),a("p",[a("code",[t._v("DECIMAL")]),t._v(" 类型主要用于精确计算,代价较高,应该尽量只在对小数进行精确计算时才使用 "),a("code",[t._v("DECIMAL")]),t._v(" ——例如存储财务数据。数据量比较大的时候,可以使用 "),a("code",[t._v("BIGINT")]),t._v(" 代替 "),a("code",[t._v("DECIMAL")]),t._v("。")]),t._v(" "),a("p",[a("code",[t._v("FLOAT")]),t._v("、"),a("code",[t._v("DOUBLE")]),t._v(" 和 "),a("code",[t._v("DECIMAL")]),t._v(" 都可以指定列宽,例如 "),a("code",[t._v("DECIMAL(18, 9)")]),t._v(" 表示总共 18 位,取 9 位存储小数部分,剩下 9 位存储整数部分。")]),t._v(" "),a("h3",{attrs:{id:"字符串"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#字符串"}},[t._v("#")]),t._v(" 字符串")]),t._v(" "),a("p",[t._v("主要有 "),a("code",[t._v("CHAR")]),t._v(" 和 "),a("code",[t._v("VARCHAR")]),t._v(" 两种类型,一种是定长的,一种是变长的。")]),t._v(" "),a("p",[a("strong",[a("code",[t._v("VARCHAR")]),t._v(" 这种变长类型能够节省空间,因为只需要存储必要的内容。但是在执行 UPDATE 时可能会使行变得比原来长")]),t._v("。当超出一个页所能容纳的大小时,就要执行额外的操作。MyISAM 会将行拆成不同的片段存储,而 InnoDB 则需要分裂页来使行放进页内。")]),t._v(" "),a("p",[a("code",[t._v("VARCHAR")]),t._v(" 会保留字符串末尾的空格,而 "),a("code",[t._v("CHAR")]),t._v(" 会删除。")]),t._v(" "),a("h3",{attrs:{id:"时间和日期"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#时间和日期"}},[t._v("#")]),t._v(" 时间和日期")]),t._v(" "),a("p",[t._v("MySQL 提供了两种相似的日期时间类型:"),a("code",[t._v("DATATIME")]),t._v(" 和 "),a("code",[t._v("TIMESTAMP")]),t._v("。")]),t._v(" "),a("h4",{attrs:{id:"datatime"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#datatime"}},[t._v("#")]),t._v(" DATATIME")]),t._v(" "),a("p",[t._v("能够保存从 1001 年到 9999 年的日期和时间,精度为秒,使用 8 字节的存储空间。")]),t._v(" "),a("p",[t._v("它与时区无关。")]),t._v(" "),a("p",[t._v("默认情况下,MySQL 以一种可排序的、无歧义的格式显示 DATATIME 值,例如“2008-01-16 22:37:08”,这是 ANSI 标准定义的日期和时间表示方法。")]),t._v(" "),a("h4",{attrs:{id:"timestamp"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#timestamp"}},[t._v("#")]),t._v(" TIMESTAMP")]),t._v(" "),a("p",[t._v("和 UNIX 时间戳相同,保存从 1970 年 1 月 1 日午夜(格林威治时间)以来的秒数,使用 4 个字节,只能表示从 1970 年 到 2038 年。")]),t._v(" "),a("p",[t._v("它和时区有关,也就是说一个时间戳在不同的时区所代表的具体时间是不同的。")]),t._v(" "),a("p",[t._v("MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提供了 UNIX_TIMESTAMP() 函数把日期转换为 UNIX 时间戳。")]),t._v(" "),a("p",[t._v("默认情况下,如果插入时没有指定 TIMESTAMP 列的值,会将这个值设置为当前时间。")]),t._v(" "),a("p",[t._v("应该尽量使用 TIMESTAMP,因为它比 DATETIME 空间效率更高。")]),t._v(" "),a("h3",{attrs:{id:"blob-和-text"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#blob-和-text"}},[t._v("#")]),t._v(" BLOB 和 TEXT")]),t._v(" "),a("p",[a("code",[t._v("BLOB")]),t._v(" 和 "),a("code",[t._v("TEXT")]),t._v(" 都是为了存储大的数据而设计,前者存储二进制数据,后者存储字符串数据。")]),t._v(" "),a("p",[t._v("不能对 "),a("code",[t._v("BLOB")]),t._v(" 和 "),a("code",[t._v("TEXT")]),t._v(" 类型的全部内容进行排序、索引。")]),t._v(" "),a("h3",{attrs:{id:"枚举类型"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#枚举类型"}},[t._v("#")]),t._v(" 枚举类型")]),t._v(" "),a("p",[t._v("大多数情况下没有使用枚举类型的必要,其中一个缺点是:枚举的字符串列表是固定的,添加和删除字符串(枚举选项)必须使用"),a("code",[t._v("ALTER TABLE")]),t._v("(如果只只是在列表末尾追加元素,不需要重建表)。")]),t._v(" "),a("h3",{attrs:{id:"类型的选择"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#类型的选择"}},[t._v("#")]),t._v(" 类型的选择")]),t._v(" "),a("ul",[a("li",[a("p",[t._v("整数类型通常是标识列最好的选择,因为它们很快并且可以使用 "),a("code",[t._v("AUTO_INCREMENT")]),t._v("。")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("ENUM")]),t._v(" 和 "),a("code",[t._v("SET")]),t._v(" 类型通常是一个糟糕的选择,应尽量避免。")])]),t._v(" "),a("li",[a("p",[t._v("应该尽量避免用字符串类型作为标识列,因为它们很消耗空间,并且通常比数字类型慢。对于 "),a("code",[t._v("MD5")]),t._v("、"),a("code",[t._v("SHA")]),t._v("、"),a("code",[t._v("UUID")]),t._v(" 这类随机字符串,由于比较随机,所以可能分布在很大的空间内,导致 "),a("code",[t._v("INSERT")]),t._v(" 以及一些 "),a("code",[t._v("SELECT")]),t._v(" 语句变得很慢。")]),t._v(" "),a("ul",[a("li",[t._v("如果存储 UUID ,应该移除 "),a("code",[t._v("-")]),t._v(" 符号;更好的做法是,用 "),a("code",[t._v("UNHEX()")]),t._v(" 函数转换 UUID 值为 16 字节的数字,并存储在一个 "),a("code",[t._v("BINARY(16)")]),t._v(" 的列中,检索时,可以通过 "),a("code",[t._v("HEX()")]),t._v(" 函数来格式化为 16 进制格式。")])])])]),t._v(" "),a("h2",{attrs:{id:"索引"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#索引"}},[t._v("#")]),t._v(" 索引")]),t._v(" "),a("blockquote",[a("p",[t._v("详见:"),a("RouterLink",{attrs:{to:"/12.数据库/03.关系型数据库/02.Mysql/05.Mysql索引.html"}},[t._v("Mysql 索引")])],1)]),t._v(" "),a("h2",{attrs:{id:"锁"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#锁"}},[t._v("#")]),t._v(" 锁")]),t._v(" "),a("blockquote",[a("p",[t._v("详见:"),a("RouterLink",{attrs:{to:"/12.数据库/03.关系型数据库/02.Mysql/04.Mysql锁.html"}},[t._v("Mysql 锁")])],1)]),t._v(" "),a("h2",{attrs:{id:"事务"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#事务"}},[t._v("#")]),t._v(" 事务")]),t._v(" "),a("blockquote",[a("p",[t._v("详见:"),a("RouterLink",{attrs:{to:"/12.数据库/03.关系型数据库/02.Mysql/03.Mysql事务.html"}},[t._v("Mysql 事务")])],1)]),t._v(" "),a("h2",{attrs:{id:"性能优化"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#性能优化"}},[t._v("#")]),t._v(" 性能优化")]),t._v(" "),a("blockquote",[a("p",[t._v("详见:"),a("RouterLink",{attrs:{to:"/12.数据库/03.关系型数据库/02.Mysql/06.Mysql性能优化.html"}},[t._v("Mysql 性能优化")])],1)]),t._v(" "),a("h2",{attrs:{id:"复制"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#复制"}},[t._v("#")]),t._v(" 复制")]),t._v(" "),a("h3",{attrs:{id:"主从复制"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#主从复制"}},[t._v("#")]),t._v(" 主从复制")]),t._v(" "),a("p",[t._v("Mysql 支持两种复制:基于行的复制和基于语句的复制。")]),t._v(" "),a("p",[t._v("这两种方式都是在主库上记录二进制日志,然后在从库重放日志的方式来实现异步的数据复制。这意味着:复制过程存在时延,这段时间内,主从数据可能不一致。")]),t._v(" "),a("p",[t._v("主要涉及三个线程:binlog 线程、I/O 线程和 SQL 线程。")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("binlog 线程")]),t._v(" :负责将主服务器上的数据更改写入二进制文件(binlog)中。")]),t._v(" "),a("li",[a("strong",[t._v("I/O 线程")]),t._v(" :负责从主服务器上读取二进制日志文件,并写入从服务器的中继日志中。")]),t._v(" "),a("li",[a("strong",[t._v("SQL 线程")]),t._v(" :负责读取中继日志并重放其中的 SQL 语句。")])]),t._v(" "),a("div",{attrs:{align:"center"}},[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/mysql/master-slave.png"}})]),t._v(" "),a("h3",{attrs:{id:"读写分离"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#读写分离"}},[t._v("#")]),t._v(" 读写分离")]),t._v(" "),a("p",[t._v("主服务器用来处理写操作以及实时性要求比较高的读操作,而从服务器用来处理读操作。")]),t._v(" "),a("p",[t._v("读写分离常用代理方式来实现,代理服务器接收应用层传来的读写请求,然后决定转发到哪个服务器。")]),t._v(" "),a("p",[t._v("MySQL 读写分离能提高性能的原因在于:")]),t._v(" "),a("ul",[a("li",[t._v("主从服务器负责各自的读和写,极大程度缓解了锁的争用;")]),t._v(" "),a("li",[t._v("从服务器可以配置 MyISAM 引擎,提升查询性能以及节约系统开销;")]),t._v(" "),a("li",[t._v("增加冗余,提高可用性。")])]),t._v(" "),a("div",{attrs:{align:"center"}},[a("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/cs/database/mysql/master-slave-proxy.png"}})]),t._v(" "),a("h2",{attrs:{id:"参考资料"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#参考资料"}},[t._v("#")]),t._v(" 参考资料")]),t._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"https://book.douban.com/subject/23008813/",target:"_blank",rel:"noopener noreferrer"}},[t._v("《高性能 MySQL》"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://www.jfox.info/20-tiao-mysql-xing-nen-you-hua-de-zui-jia-jing-yan.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("20+ 条 MySQL 性能优化的最佳经验"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://stackoverflow.com/questions/788829/how-to-create-unique-row-id-in-sharded-databases",target:"_blank",rel:"noopener noreferrer"}},[t._v("How to create unique row ID in sharded databases?"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"http://geekswithblogs.net/shaunxu/archive/2012/01/07/sql-azure-federation-ndash-introduction.aspx",target:"_blank",rel:"noopener noreferrer"}},[t._v("SQL Azure Federation – Introduction"),a("OutboundLink")],1)])]),t._v(" "),a("h2",{attrs:{id:"传送门"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#传送门"}},[t._v("#")]),t._v(" 传送门")]),t._v(" "),a("p",[t._v("◾ 💧 "),a("a",{attrs:{href:"https://dunwu.github.io/waterdrop/",target:"_blank",rel:"noopener noreferrer"}},[t._v("钝悟的 IT 知识图谱"),a("OutboundLink")],1),t._v(" ◾ 🎯 "),a("a",{attrs:{href:"https://dunwu.github.io/blog/",target:"_blank",rel:"noopener noreferrer"}},[t._v("钝悟的博客"),a("OutboundLink")],1),t._v(" ◾")])])}),[],!1,null,null,null);a.default=e.exports}}]);
\ No newline at end of file
diff --git a/assets/js/19.a32eb894.js b/assets/js/19.a32eb894.js
new file mode 100644
index 00000000..cbd5fc48
--- /dev/null
+++ b/assets/js/19.a32eb894.js
@@ -0,0 +1 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{356:function(t,r,s){"use strict";s.r(r);var a=s(4),e=Object(a.a)({},(function(){var t=this,r=t._self._c;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h1",{attrs:{id:"mysql-工作流"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#mysql-工作流"}},[t._v("#")]),t._v(" MySQL 工作流")]),t._v(" "),r("h2",{attrs:{id:"基础架构"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#基础架构"}},[t._v("#")]),t._v(" 基础架构")]),t._v(" "),r("p",[t._v("大体来说,MySQL 可以分为 Server 层和存储引擎层两部分。")]),t._v(" "),r("p",[r("strong",[t._v("Server 层包括连接器、查询缓存、分析器、优化器、执行器等")]),t._v(",涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。")]),t._v(" "),r("p",[r("strong",[t._v("存储引擎层负责数据的存储和提取")]),t._v("。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始成为了默认存储引擎。")]),t._v(" "),r("p",[r("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/snap/20200227201908.jpg",alt:"img"}})]),t._v(" "),r("h2",{attrs:{id:"查询过程"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#查询过程"}},[t._v("#")]),t._v(" 查询过程")]),t._v(" "),r("p",[t._v("SQL 语句在 MySQL 中是如何执行的?")]),t._v(" "),r("p",[t._v("MySQL 整个查询执行过程,总的来说分为 6 个步骤,分别对应 6 个组件:")]),t._v(" "),r("ol",[r("li",[t._v("连接器:客户端和 MySQL 服务器建立连接;连接器负责跟客户端建立连接、获取权限、维持和管理连接。")]),t._v(" "),r("li",[t._v("MySQL 服务器首先检查查询缓存,如果命中缓存,则立刻返回结果。否则进入下一阶段。")]),t._v(" "),r("li",[t._v("MySQL 服务器进行 SQL 分析:语法分析、词法分析。")]),t._v(" "),r("li",[t._v("MySQL 服务器用优化器生成对应的执行计划。")]),t._v(" "),r("li",[t._v("MySQL 服务器根据执行计划,调用存储引擎的 API 来执行查询。")]),t._v(" "),r("li",[t._v("MySQL 服务器将结果返回给客户端,同时缓存查询结果。")])]),t._v(" "),r("h3",{attrs:{id:"一-连接器"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#一-连接器"}},[t._v("#")]),t._v(" (一)连接器")]),t._v(" "),r("p",[t._v("使用 MySQL 第一步自然是要连接数据库。"),r("strong",[t._v("连接器负责跟客户端建立连接、获取权限、维持和管理连接")]),t._v("。")]),t._v(" "),r("p",[t._v("MySQL 客户端/服务端通信是"),r("strong",[t._v("半双工模式")]),t._v(":即任一时刻,要么是服务端向客户端发送数据,要么是客户端向服务器发送数据。客户端用一个单独的数据包将查询请求发送给服务器,所以当查询语句很长的时候,需要设置"),r("code",[t._v("max_allowed_packet")]),t._v("参数。但是需要注意的是,如果查询实在是太大,服务端会拒绝接收更多数据并抛出异常。")]),t._v(" "),r("p",[t._v("MySQL 客户端连接命令:"),r("code",[t._v("mysql -h<主机> -P<端口> -u<用户名> -p<密码>")]),t._v("。如果没有显式指定密码,会要求输入密码才能访问。")]),t._v(" "),r("p",[t._v("连接完成后,如果你没有后续的动作,这个连接就处于空闲状态,你可以在 "),r("code",[t._v("show processlist")]),t._v(" 命令中看到它。客户端如果太长时间没动静,连接器就会自动将它断开。"),r("strong",[t._v("客户端连接维持时间是由参数 "),r("code",[t._v("wait_timeout")]),t._v(" 控制的,默认值是 8 小时")]),t._v("。如果在连接被断开之后,客户端再次发送请求的话,就会收到一个错误提醒: "),r("code",[t._v("Lost connection to MySQL server during query")]),t._v("。这时候如果你要继续,就需要重连,然后再执行请求了。")]),t._v(" "),r("p",[t._v("建立连接的过程通常是比较复杂的,建议在使用中要尽量减少建立连接的动作,也就是尽量使用长连接。为了在程序中提高数据库连接的服用了,一般会使用数据库连接池来维护管理。")]),t._v(" "),r("p",[t._v("但是全部使用长连接后,你可能会发现,有些时候 MySQL 占用内存涨得特别快,这是因为 MySQL 在执行过程中临时使用的内存是管理在连接对象里面的。这些资源会在连接断开的时候才释放。所以如果长连接累积下来,可能导致内存占用太大,被系统强行杀掉(OOM),从现象看就是 MySQL 异常重启了。")]),t._v(" "),r("p",[t._v("怎么解决这个问题呢?你可以考虑以下两种方案。")]),t._v(" "),r("ul",[r("li",[r("strong",[t._v("定期断开长连接")]),t._v("。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。")]),t._v(" "),r("li",[t._v("如果你用的是 MySQL 5.7 或更新版本,可以在每次执行一个比较大的操作后,通过执行 "),r("code",[t._v("mysql_reset_connection")]),t._v(" 来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态。")])]),t._v(" "),r("h3",{attrs:{id:"二-查询缓存"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#二-查询缓存"}},[t._v("#")]),t._v(" (二)查询缓存")]),t._v(" "),r("blockquote",[r("p",[r("strong",[t._v("不建议使用数据库缓存,因为往往弊大于利")]),t._v("。")])]),t._v(" "),r("p",[t._v("解析一个查询语句前,如果查询缓存是打开的,那么 MySQL 会检查这个查询语句是否命中查询缓存中的数据。如果当前查询恰好命中查询缓存,在检查一次用户权限后直接返回缓存中的结果。这种情况下,查询不会被解析,也不会生成执行计划,更不会执行。")]),t._v(" "),r("p",[t._v("MySQL 将缓存存放在一个引用表(不要理解成"),r("code",[t._v("table")]),t._v(",可以认为是类似于"),r("code",[t._v("HashMap")]),t._v("的数据结构),通过一个哈希值索引,这个哈希值通过查询本身、当前要查询的数据库、客户端协议版本号等一些可能影响结果的信息计算得来。所以两个查询在任何字符上的不同(例如:空格、注释),都会导致缓存不会命中。")]),t._v(" "),r("p",[r("strong",[t._v("如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、mysql 库中的系统表,其查询结果都不会被缓存")]),t._v("。比如函数"),r("code",[t._v("NOW()")]),t._v("或者"),r("code",[t._v("CURRENT_DATE()")]),t._v("会因为不同的查询时间,返回不同的查询结果,再比如包含"),r("code",[t._v("CURRENT_USER")]),t._v("或者"),r("code",[t._v("CONNECION_ID()")]),t._v("的查询语句会因为不同的用户而返回不同的结果,将这样的查询结果缓存起来没有任何的意义。")]),t._v(" "),r("p",[r("strong",[t._v("不建议使用数据库缓存,因为往往弊大于利")]),t._v("。查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。因此很可能你费劲地把结果存起来,还没使用呢,就被一个更新全清空了。对于更新压力大的数据库来说,查询缓存的命中率会非常低。除非你的业务就是有一张静态表,很长时间才会更新一次。比如,一个系统配置表,那这张表上的查询才适合使用查询缓存。")]),t._v(" "),r("p",[t._v("好在 MySQL 也提供了这种“按需使用”的方式。你可以将参数 "),r("code",[t._v("query_cache_type")]),t._v(" 设置成 "),r("code",[t._v("DEMAND")]),t._v(",这样对于默认的 SQL 语句都不使用查询缓存。而对于你确定要使用查询缓存的语句,可以用 "),r("code",[t._v("SQL_CACHE")]),t._v(" 显式指定,像下面这个语句一样:")]),t._v(" "),r("div",{staticClass:"language-sql extra-class"},[r("pre",{pre:!0,attrs:{class:"language-sql"}},[r("code",[r("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" SQL_CACHE "),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),r("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" T "),r("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v(" ID"),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),r("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),r("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),r("blockquote",[r("p",[t._v("注意:MySQL 8.0 版本直接将查询缓存的整块功能删掉了。")])]),t._v(" "),r("h3",{attrs:{id:"三-语法分析"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#三-语法分析"}},[t._v("#")]),t._v(" (三)语法分析")]),t._v(" "),r("p",[t._v("如果没有命中查询缓存,就要开始真正执行语句了。首先,MySQL 需要知道你要做什么,因此需要对 SQL 语句做解析。MySQL 通过关键字对 SQL 语句进行解析,并生成一颗对应的语法解析树。这个过程中,分析器主要通过语法规则来验证和解析。比如 SQL 中是否使用了错误的关键字或者关键字的顺序是否正确等等。预处理则会根据 MySQL 规则进一步检查解析树是否合法。比如检查要查询的数据表和数据列是否存在等等。")]),t._v(" "),r("ul",[r("li",[t._v("分析器先会先做“"),r("strong",[t._v("词法分析")]),t._v('”。你输入的是由多个字符串和空格组成的一条 SQL 语句,MySQL 需要识别出里面的字符串分别是什么,代表什么。MySQL 从你输入的"select"这个关键字识别出来,这是一个查询语句。它也要把字符串“T”识别成“表名 T”,把字符串“ID”识别成“列 ID”。')]),t._v(" "),r("li",[t._v("接下来,要做“"),r("strong",[t._v("语法分析")]),t._v("”。根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法。如果你的语句不对,就会收到“You have an error in your SQL syntax”的错误提醒,比如下面这个语句 select 少打了开头的字母“s”。")])]),t._v(" "),r("h3",{attrs:{id:"四-查询优化"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#四-查询优化"}},[t._v("#")]),t._v(" (四)查询优化")]),t._v(" "),r("p",[t._v("经过了分析器,MySQL 就知道你要做什么了。在开始执行之前,还要先经过优化器的处理。")]),t._v(" "),r("p",[t._v("经过前面的步骤生成的语法树被认为是合法的了,并且由优化器将其转化成执行计划。多数情况下,一条查询可以有很多种执行方式,最后都返回相应的结果。优化器的作用就是找到这其中最好的执行计划。")]),t._v(" "),r("p",[t._v("MySQL 使用基于成本的优化器,它尝试预测一个查询使用某种执行计划时的成本,并选择其中成本最小的一个。在 MySQL 可以通过查询当前会话的 "),r("code",[t._v("last_query_cost")]),t._v(" 的值来得到其计算当前查询的成本。")]),t._v(" "),r("div",{staticClass:"language-ruby extra-class"},[r("pre",{pre:!0,attrs:{class:"language-ruby"}},[r("code",[t._v("mysql"),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" select "),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" from t_message limit "),r("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),r("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("省略结果集\n\nmysql"),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" show status like "),r("span",{pre:!0,attrs:{class:"token string-literal"}},[r("span",{pre:!0,attrs:{class:"token string"}},[t._v("'last_query_cost'")])]),r("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v("\n"),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" Variable_name "),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" Value "),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n"),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v("\n"),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" Last_query_cost "),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),r("span",{pre:!0,attrs:{class:"token number"}},[t._v("6391.799000")]),t._v(" "),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n"),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),r("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v("\n")])])]),r("p",[t._v("示例中的结果表示优化器认为大概需要做 6391 个数据页的随机查找才能完成上面的查询。这个结果是根据一些列的统计信息计算得来的,这些统计信息包括:每张表或者索引的页面个数、索引的基数、索引和数据行的长度、索引的分布情况等等。")]),t._v(" "),r("p",[t._v("有非常多的原因会导致 MySQL 选择错误的执行计划,比如统计信息不准确、不会考虑不受其控制的操作成本(用户自定义函数、存储过程)、MySQL 认为的最优跟我们想的不一样(我们希望执行时间尽可能短,但 MySQL 值选择它认为成本小的,但成本小并不意味着执行时间短)等等。")]),t._v(" "),r("p",[t._v("MySQL 的查询优化器是一个非常复杂的部件,它使用了非常多的优化策略来生成一个最优的执行计划:")]),t._v(" "),r("ul",[r("li",[t._v("重新定义表的关联顺序(多张表关联查询时,并不一定按照 SQL 中指定的顺序进行,但有一些技巧可以指定关联顺序)")]),t._v(" "),r("li",[t._v("优化"),r("code",[t._v("MIN()")]),t._v("和"),r("code",[t._v("MAX()")]),t._v("函数(找某列的最小值,如果该列有索引,只需要查找 B+Tree 索引最左端,反之则可以找到最大值,具体原理见下文)")]),t._v(" "),r("li",[t._v("提前终止查询(比如:使用 Limit 时,查找到满足数量的结果集后会立即终止查询)")]),t._v(" "),r("li",[t._v("优化排序(在老版本 MySQL 会使用两次传输排序,即先读取行指针和需要排序的字段在内存中对其排序,然后再根据排序结果去读取数据行,而新版本采用的是单次传输排序,也就是一次读取所有的数据行,然后根据给定的列排序。对于 I/O 密集型应用,效率会高很多)")])]),t._v(" "),r("p",[t._v("随着 MySQL 的不断发展,优化器使用的优化策略也在不断的进化,这里仅仅介绍几个非常常用且容易理解的优化策略,其他的优化策略,大家自行查阅吧。")]),t._v(" "),r("h3",{attrs:{id:"五-查询执行引擎"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#五-查询执行引擎"}},[t._v("#")]),t._v(" (五)查询执行引擎")]),t._v(" "),r("p",[t._v("在完成解析和优化阶段以后,MySQL 会生成对应的执行计划,查询执行引擎根据执行计划给出的指令逐步执行得出结果。整个执行过程的大部分操作均是通过调用存储引擎实现的接口来完成,这些接口被称为"),r("code",[t._v("handler API")]),t._v("。查询过程中的每一张表由一个"),r("code",[t._v("handler")]),t._v("实例表示。实际上,MySQL 在查询优化阶段就为每一张表创建了一个"),r("code",[t._v("handler")]),t._v("实例,优化器可以根据这些实例的接口来获取表的相关信息,包括表的所有列名、索引统计信息等。存储引擎接口提供了非常丰富的功能,但其底层仅有几十个接口,这些接口像搭积木一样完成了一次查询的大部分操作。")]),t._v(" "),r("h3",{attrs:{id:"六-返回结果"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#六-返回结果"}},[t._v("#")]),t._v(" (六)返回结果")]),t._v(" "),r("p",[t._v("查询过程的最后一个阶段就是将结果返回给客户端。即使查询不到数据,MySQL 仍然会返回这个查询的相关信息,比如该查询影响到的行数以及执行时间等等。")]),t._v(" "),r("p",[t._v("如果查询缓存被打开且这个查询可以被缓存,MySQL 也会将结果存放到缓存中。")]),t._v(" "),r("p",[t._v("结果集返回客户端是一个增量且逐步返回的过程。有可能 MySQL 在生成第一条结果时,就开始向客户端逐步返回结果集了。这样服务端就无须存储太多结果而消耗过多内存,也可以让客户端第一时间获得返回结果。需要注意的是,结果集中的每一行都会以一个满足 ① 中所描述的通信协议的数据包发送,再通过 TCP 协议进行传输,在传输过程中,可能对 MySQL 的数据包进行缓存然后批量发送。")]),t._v(" "),r("h2",{attrs:{id:"更新过程"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#更新过程"}},[t._v("#")]),t._v(" 更新过程")]),t._v(" "),r("p",[t._v("MySQL 更新过程和 MySQL 查询过程类似,也会将流程走一遍。不一样的是:"),r("strong",[t._v("更新流程还涉及两个重要的日志模块,:redo log(重做日志)和 binlog(归档日志)")]),t._v("。")]),t._v(" "),r("h3",{attrs:{id:"redo-log"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#redo-log"}},[t._v("#")]),t._v(" redo log")]),t._v(" "),r("p",[r("strong",[t._v("redo log 是 InnoDB 引擎特有的日志")]),t._v("。"),r("strong",[t._v("redo log 即重做日志")]),t._v("。redo log 是物理日志,记录的是“在某个数据页上做了什么修改”。")]),t._v(" "),r("p",[r("strong",[t._v("redo log 是基于 WAL 技术")]),t._v("。WAL 的全称是 "),r("strong",[t._v("Write-Ahead Logging")]),t._v(",它的关键点就是"),r("strong",[t._v("先写日志,再写磁盘")]),t._v("。具体来说,当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log 里,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做。")]),t._v(" "),r("p",[t._v("InnoDB 的 redo log 是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是 1GB,那么这块“粉板”总共就可以记录 4GB 的操作。从头开始写,写到末尾就又回到开头循环写。")]),t._v(" "),r("p",[r("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/snap/20200630180342.png",alt:"img"}})]),t._v(" "),r("p",[t._v("有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为"),r("strong",[t._v("crash-safe")]),t._v("。")]),t._v(" "),r("h3",{attrs:{id:"bin-log"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#bin-log"}},[t._v("#")]),t._v(" bin log")]),t._v(" "),r("p",[r("strong",[t._v("bin log 即归档日志")]),t._v("。binlog 是逻辑日志,记录的是这个语句的原始逻辑。")]),t._v(" "),r("p",[t._v("binlog 是可以追加写入的,即写到一定大小后会切换到下一个,并不会覆盖以前的日志。")]),t._v(" "),r("p",[r("strong",[t._v("binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用")]),t._v("。")]),t._v(" "),r("p",[r("code",[t._v("sync_binlog")]),t._v(" 这个参数设置成 1 的时候,表示每次事务的 binlog 都持久化到磁盘。这个参数我也建议你设置成 1,这样可以保证 MySQL 异常重启之后 binlog 不丢失。")]),t._v(" "),r("h3",{attrs:{id:"redo-log-vs-bin-log"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#redo-log-vs-bin-log"}},[t._v("#")]),t._v(" redo log vs. bin log")]),t._v(" "),r("p",[t._v("这两种日志有以下三点不同。")]),t._v(" "),r("ul",[r("li",[t._v("redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。")]),t._v(" "),r("li",[t._v("redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。")]),t._v(" "),r("li",[t._v("redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。")])]),t._v(" "),r("p",[t._v("有了对这两个日志的概念性理解,我们再来看执行器和 InnoDB 引擎在执行这个简单的 update 语句时的内部流程。")]),t._v(" "),r("ol",[r("li",[t._v("执行器先找引擎取 ID=2 这一行。ID 是主键,引擎直接用树搜索找到这一行。如果 ID=2 这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。")]),t._v(" "),r("li",[t._v("执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。")]),t._v(" "),r("li",[t._v("引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务。")]),t._v(" "),r("li",[t._v("执行器生成这个操作的 binlog,并把 binlog 写入磁盘。")]),t._v(" "),r("li",[t._v("执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。")])]),t._v(" "),r("p",[t._v("这里我给出这个 update 语句的执行流程图,图中浅色框表示是在 InnoDB 内部执行的,深色框表示是在执行器中执行的。")]),t._v(" "),r("p",[r("img",{attrs:{src:"https://raw.githubusercontent.com/dunwu/images/dev/snap/20200714133806.png",alt:"img"}})]),t._v(" "),r("h3",{attrs:{id:"两阶段提交"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#两阶段提交"}},[t._v("#")]),t._v(" 两阶段提交")]),t._v(" "),r("p",[t._v('redo log 的写入拆成了两个步骤:prepare 和 commit,这就是"两阶段提交"。为什么日志需要“两阶段提交”。')]),t._v(" "),r("p",[t._v("由于 redo log 和 binlog 是两个独立的逻辑,如果不用两阶段提交,要么就是先写完 redo log 再写 binlog,或者采用反过来的顺序。我们看看这两种方式会有什么问题。")]),t._v(" "),r("ul",[r("li",[r("strong",[t._v("先写 redo log 后写 binlog")]),t._v("。假设在 redo log 写完,binlog 还没有写完的时候,MySQL 进程异常重启。由于我们前面说过的,redo log 写完之后,系统即使崩溃,仍然能够把数据恢复回来,所以恢复后这一行 c 的值是 1。\n但是由于 binlog 没写完就 crash 了,这时候 binlog 里面就没有记录这个语句。因此,之后备份日志的时候,存起来的 binlog 里面就没有这条语句。\n然后你会发现,如果需要用这个 binlog 来恢复临时库的话,由于这个语句的 binlog 丢失,这个临时库就会少了这一次更新,恢复出来的这一行 c 的值就是 0,与原库的值不同。")]),t._v(" "),r("li",[r("strong",[t._v("先写 binlog 后写 redo log")]),t._v("。如果在 binlog 写完之后 crash,由于 redo log 还没写,崩溃恢复以后这个事务无效,所以这一行 c 的值是 0。但是 binlog 里面已经记录了“把 c 从 0 改成 1”这个日志。所以,在之后用 binlog 来恢复的时候就多了一个事务出来,恢复出来的这一行 c 的值就是 1,与原库的值不同。")])]),t._v(" "),r("p",[t._v("可以看到,如果不使用“两阶段提交”,那么数据库的状态就有可能和用它的日志恢复出来的库的状态不一致。")]),t._v(" "),r("h2",{attrs:{id:"参考资料"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#参考资料"}},[t._v("#")]),t._v(" 参考资料")]),t._v(" "),r("ul",[r("li",[r("a",{attrs:{href:"https://book.douban.com/subject/23008813/",target:"_blank",rel:"noopener noreferrer"}},[t._v("《高性能 MySQL》"),r("OutboundLink")],1)]),t._v(" "),r("li",[r("a",{attrs:{href:"https://time.geekbang.org/column/intro/139",target:"_blank",rel:"noopener noreferrer"}},[t._v("MySQL 实战 45 讲"),r("OutboundLink")],1)])])])}),[],!1,null,null,null);r.default=e.exports}}]);
\ No newline at end of file
diff --git a/assets/js/2.da1ec370.js b/assets/js/2.da1ec370.js
new file mode 100644
index 00000000..fc249919
--- /dev/null
+++ b/assets/js/2.da1ec370.js
@@ -0,0 +1,14 @@
+(window.webpackJsonp=window.webpackJsonp||[]).push([[2],Array(257).concat([function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){(function(t){var r;
+/**
+ * @license
+ * Lodash
+ * Copyright OpenJS Foundation and other contributors
+ * Released under MIT license
+ * Based on Underscore.js 1.8.3
+ * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ */(function(){var i="Expected a function",o="__lodash_placeholder__",s=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],a="[object Arguments]",u="[object Array]",l="[object Boolean]",c="[object Date]",h="[object Error]",f="[object Function]",p="[object GeneratorFunction]",g="[object Map]",d="[object Number]",v="[object Object]",m="[object RegExp]",y="[object Set]",_="[object String]",b="[object Symbol]",w="[object WeakMap]",k="[object ArrayBuffer]",x="[object DataView]",P="[object Float32Array]",C="[object Float64Array]",T="[object Int8Array]",S="[object Int16Array]",L="[object Int32Array]",A="[object Uint8Array]",B="[object Uint16Array]",O="[object Uint32Array]",M=/\b__p \+= '';/g,E=/\b(__p \+=) '' \+/g,I=/(__e\(.*?\)|\b__t\)) \+\n'';/g,D=/&(?:amp|lt|gt|quot|#39);/g,$=/[&<>"']/g,j=RegExp(D.source),Y=RegExp($.source),X=/<%-([\s\S]+?)%>/g,N=/<%([\s\S]+?)%>/g,z=/<%=([\s\S]+?)%>/g,R=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,H=/^\w*$/,U=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,F=/[\\^$.*+?()[\]{}|]/g,W=RegExp(F.source),q=/^\s+/,G=/\s/,K=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,Q=/\{\n\/\* \[wrapped with (.+)\] \*/,J=/,? & /,Z=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,V=/[()=,{}\[\]\/\s]/,tt=/\\(\\)?/g,et=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,nt=/\w*$/,rt=/^[-+]0x[0-9a-f]+$/i,it=/^0b[01]+$/i,ot=/^\[object .+?Constructor\]$/,st=/^0o[0-7]+$/i,at=/^(?:0|[1-9]\d*)$/,ut=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,lt=/($^)/,ct=/['\n\r\u2028\u2029\\]/g,ht="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",ft="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",pt="[\\ud800-\\udfff]",gt="["+ft+"]",dt="["+ht+"]",vt="\\d+",mt="[\\u2700-\\u27bf]",yt="[a-z\\xdf-\\xf6\\xf8-\\xff]",_t="[^\\ud800-\\udfff"+ft+vt+"\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde]",bt="\\ud83c[\\udffb-\\udfff]",wt="[^\\ud800-\\udfff]",kt="(?:\\ud83c[\\udde6-\\uddff]){2}",xt="[\\ud800-\\udbff][\\udc00-\\udfff]",Pt="[A-Z\\xc0-\\xd6\\xd8-\\xde]",Ct="(?:"+yt+"|"+_t+")",Tt="(?:"+Pt+"|"+_t+")",St="(?:"+dt+"|"+bt+")"+"?",Lt="[\\ufe0e\\ufe0f]?"+St+("(?:\\u200d(?:"+[wt,kt,xt].join("|")+")[\\ufe0e\\ufe0f]?"+St+")*"),At="(?:"+[mt,kt,xt].join("|")+")"+Lt,Bt="(?:"+[wt+dt+"?",dt,kt,xt,pt].join("|")+")",Ot=RegExp("['’]","g"),Mt=RegExp(dt,"g"),Et=RegExp(bt+"(?="+bt+")|"+Bt+Lt,"g"),It=RegExp([Pt+"?"+yt+"+(?:['’](?:d|ll|m|re|s|t|ve))?(?="+[gt,Pt,"$"].join("|")+")",Tt+"+(?:['’](?:D|LL|M|RE|S|T|VE))?(?="+[gt,Pt+Ct,"$"].join("|")+")",Pt+"?"+Ct+"+(?:['’](?:d|ll|m|re|s|t|ve))?",Pt+"+(?:['’](?:D|LL|M|RE|S|T|VE))?","\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",vt,At].join("|"),"g"),Dt=RegExp("[\\u200d\\ud800-\\udfff"+ht+"\\ufe0e\\ufe0f]"),$t=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,jt=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Yt=-1,Xt={};Xt[P]=Xt[C]=Xt[T]=Xt[S]=Xt[L]=Xt[A]=Xt["[object Uint8ClampedArray]"]=Xt[B]=Xt[O]=!0,Xt[a]=Xt[u]=Xt[k]=Xt[l]=Xt[x]=Xt[c]=Xt[h]=Xt[f]=Xt[g]=Xt[d]=Xt[v]=Xt[m]=Xt[y]=Xt[_]=Xt[w]=!1;var Nt={};Nt[a]=Nt[u]=Nt[k]=Nt[x]=Nt[l]=Nt[c]=Nt[P]=Nt[C]=Nt[T]=Nt[S]=Nt[L]=Nt[g]=Nt[d]=Nt[v]=Nt[m]=Nt[y]=Nt[_]=Nt[b]=Nt[A]=Nt["[object Uint8ClampedArray]"]=Nt[B]=Nt[O]=!0,Nt[h]=Nt[f]=Nt[w]=!1;var zt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Rt=parseFloat,Ht=parseInt,Ut="object"==typeof global&&global&&global.Object===Object&&global,Ft="object"==typeof self&&self&&self.Object===Object&&self,Wt=Ut||Ft||Function("return this")(),qt=e&&!e.nodeType&&e,Gt=qt&&"object"==typeof t&&t&&!t.nodeType&&t,Kt=Gt&&Gt.exports===qt,Qt=Kt&&Ut.process,Jt=function(){try{var t=Gt&&Gt.require&&Gt.require("util").types;return t||Qt&&Qt.binding&&Qt.binding("util")}catch(t){}}(),Zt=Jt&&Jt.isArrayBuffer,Vt=Jt&&Jt.isDate,te=Jt&&Jt.isMap,ee=Jt&&Jt.isRegExp,ne=Jt&&Jt.isSet,re=Jt&&Jt.isTypedArray;function ie(t,e,n){switch(n.length){case 0:return t.call(e);case 1:return t.call(e,n[0]);case 2:return t.call(e,n[0],n[1]);case 3:return t.call(e,n[0],n[1],n[2])}return t.apply(e,n)}function oe(t,e,n,r){for(var i=-1,o=null==t?0:t.length;++i-1}function he(t,e,n){for(var r=-1,i=null==t?0:t.length;++r-1;);return n}function Ie(t,e){for(var n=t.length;n--&&be(e,t[n],0)>-1;);return n}function De(t,e){for(var n=t.length,r=0;n--;)t[n]===e&&++r;return r}var $e=Ce({"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss","Ā":"A","Ă":"A","Ą":"A","ā":"a","ă":"a","ą":"a","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","ć":"c","ĉ":"c","ċ":"c","č":"c","Ď":"D","Đ":"D","ď":"d","đ":"d","Ē":"E","Ĕ":"E","Ė":"E","Ę":"E","Ě":"E","ē":"e","ĕ":"e","ė":"e","ę":"e","ě":"e","Ĝ":"G","Ğ":"G","Ġ":"G","Ģ":"G","ĝ":"g","ğ":"g","ġ":"g","ģ":"g","Ĥ":"H","Ħ":"H","ĥ":"h","ħ":"h","Ĩ":"I","Ī":"I","Ĭ":"I","Į":"I","İ":"I","ĩ":"i","ī":"i","ĭ":"i","į":"i","ı":"i","Ĵ":"J","ĵ":"j","Ķ":"K","ķ":"k","ĸ":"k","Ĺ":"L","Ļ":"L","Ľ":"L","Ŀ":"L","Ł":"L","ĺ":"l","ļ":"l","ľ":"l","ŀ":"l","ł":"l","Ń":"N","Ņ":"N","Ň":"N","Ŋ":"N","ń":"n","ņ":"n","ň":"n","ŋ":"n","Ō":"O","Ŏ":"O","Ő":"O","ō":"o","ŏ":"o","ő":"o","Ŕ":"R","Ŗ":"R","Ř":"R","ŕ":"r","ŗ":"r","ř":"r","Ś":"S","Ŝ":"S","Ş":"S","Š":"S","ś":"s","ŝ":"s","ş":"s","š":"s","Ţ":"T","Ť":"T","Ŧ":"T","ţ":"t","ť":"t","ŧ":"t","Ũ":"U","Ū":"U","Ŭ":"U","Ů":"U","Ű":"U","Ų":"U","ũ":"u","ū":"u","ŭ":"u","ů":"u","ű":"u","ų":"u","Ŵ":"W","ŵ":"w","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Ź":"Z","Ż":"Z","Ž":"Z","ź":"z","ż":"z","ž":"z","IJ":"IJ","ij":"ij","Œ":"Oe","œ":"oe","ʼn":"'n","ſ":"s"}),je=Ce({"&":"&","<":"<",">":">",'"':""","'":"'"});function Ye(t){return"\\"+zt[t]}function Xe(t){return Dt.test(t)}function Ne(t){var e=-1,n=Array(t.size);return t.forEach((function(t,r){n[++e]=[r,t]})),n}function ze(t,e){return function(n){return t(e(n))}}function Re(t,e){for(var n=-1,r=t.length,i=0,s=[];++n",""":'"',"'":"'"});var Ke=function t(e){var n,r=(e=null==e?Wt:Ke.defaults(Wt.Object(),e,Ke.pick(Wt,jt))).Array,G=e.Date,ht=e.Error,ft=e.Function,pt=e.Math,gt=e.Object,dt=e.RegExp,vt=e.String,mt=e.TypeError,yt=r.prototype,_t=ft.prototype,bt=gt.prototype,wt=e["__core-js_shared__"],kt=_t.toString,xt=bt.hasOwnProperty,Pt=0,Ct=(n=/[^.]+$/.exec(wt&&wt.keys&&wt.keys.IE_PROTO||""))?"Symbol(src)_1."+n:"",Tt=bt.toString,St=kt.call(gt),Lt=Wt._,At=dt("^"+kt.call(xt).replace(F,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Bt=Kt?e.Buffer:void 0,Et=e.Symbol,Dt=e.Uint8Array,zt=Bt?Bt.allocUnsafe:void 0,Ut=ze(gt.getPrototypeOf,gt),Ft=gt.create,qt=bt.propertyIsEnumerable,Gt=yt.splice,Qt=Et?Et.isConcatSpreadable:void 0,Jt=Et?Et.iterator:void 0,me=Et?Et.toStringTag:void 0,Ce=function(){try{var t=to(gt,"defineProperty");return t({},"",{}),t}catch(t){}}(),Qe=e.clearTimeout!==Wt.clearTimeout&&e.clearTimeout,Je=G&&G.now!==Wt.Date.now&&G.now,Ze=e.setTimeout!==Wt.setTimeout&&e.setTimeout,Ve=pt.ceil,tn=pt.floor,en=gt.getOwnPropertySymbols,nn=Bt?Bt.isBuffer:void 0,rn=e.isFinite,on=yt.join,sn=ze(gt.keys,gt),an=pt.max,un=pt.min,ln=G.now,cn=e.parseInt,hn=pt.random,fn=yt.reverse,pn=to(e,"DataView"),gn=to(e,"Map"),dn=to(e,"Promise"),vn=to(e,"Set"),mn=to(e,"WeakMap"),yn=to(gt,"create"),_n=mn&&new mn,bn={},wn=Lo(pn),kn=Lo(gn),xn=Lo(dn),Pn=Lo(vn),Cn=Lo(mn),Tn=Et?Et.prototype:void 0,Sn=Tn?Tn.valueOf:void 0,Ln=Tn?Tn.toString:void 0;function An(t){if(Fs(t)&&!Is(t)&&!(t instanceof En)){if(t instanceof Mn)return t;if(xt.call(t,"__wrapped__"))return Ao(t)}return new Mn(t)}var Bn=function(){function t(){}return function(e){if(!Us(e))return{};if(Ft)return Ft(e);t.prototype=e;var n=new t;return t.prototype=void 0,n}}();function On(){}function Mn(t,e){this.__wrapped__=t,this.__actions__=[],this.__chain__=!!e,this.__index__=0,this.__values__=void 0}function En(t){this.__wrapped__=t,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function In(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e=e?t:e)),t}function Jn(t,e,n,r,i,o){var s,u=1&e,h=2&e,w=4&e;if(n&&(s=i?n(t,r,i,o):n(t)),void 0!==s)return s;if(!Us(t))return t;var M=Is(t);if(M){if(s=function(t){var e=t.length,n=new t.constructor(e);e&&"string"==typeof t[0]&&xt.call(t,"index")&&(n.index=t.index,n.input=t.input);return n}(t),!u)return yi(t,s)}else{var E=ro(t),I=E==f||E==p;if(Ys(t))return fi(t,u);if(E==v||E==a||I&&!i){if(s=h||I?{}:oo(t),!u)return h?function(t,e){return _i(t,no(t),e)}(t,function(t,e){return t&&_i(e,ka(e),t)}(s,t)):function(t,e){return _i(t,eo(t),e)}(t,qn(s,t))}else{if(!Nt[E])return i?t:{};s=function(t,e,n){var r=t.constructor;switch(e){case k:return pi(t);case l:case c:return new r(+t);case x:return function(t,e){var n=e?pi(t.buffer):t.buffer;return new t.constructor(n,t.byteOffset,t.byteLength)}(t,n);case P:case C:case T:case S:case L:case A:case"[object Uint8ClampedArray]":case B:case O:return gi(t,n);case g:return new r;case d:case _:return new r(t);case m:return function(t){var e=new t.constructor(t.source,nt.exec(t));return e.lastIndex=t.lastIndex,e}(t);case y:return new r;case b:return i=t,Sn?gt(Sn.call(i)):{}}var i}(t,E,u)}}o||(o=new Yn);var D=o.get(t);if(D)return D;o.set(t,s),Qs(t)?t.forEach((function(r){s.add(Jn(r,e,n,r,t,o))})):Ws(t)&&t.forEach((function(r,i){s.set(i,Jn(r,e,n,i,t,o))}));var $=M?void 0:(w?h?qi:Wi:h?ka:wa)(t);return se($||t,(function(r,i){$&&(r=t[i=r]),Un(s,i,Jn(r,e,n,i,t,o))})),s}function Zn(t,e,n){var r=n.length;if(null==t)return!r;for(t=gt(t);r--;){var i=n[r],o=e[i],s=t[i];if(void 0===s&&!(i in t)||!o(s))return!1}return!0}function Vn(t,e,n){if("function"!=typeof t)throw new mt(i);return wo((function(){t.apply(void 0,n)}),e)}function tr(t,e,n,r){var i=-1,o=ce,s=!0,a=t.length,u=[],l=e.length;if(!a)return u;n&&(e=fe(e,Be(n))),r?(o=he,s=!1):e.length>=200&&(o=Me,s=!1,e=new jn(e));t:for(;++i-1},Dn.prototype.set=function(t,e){var n=this.__data__,r=Fn(n,t);return r<0?(++this.size,n.push([t,e])):n[r][1]=e,this},$n.prototype.clear=function(){this.size=0,this.__data__={hash:new In,map:new(gn||Dn),string:new In}},$n.prototype.delete=function(t){var e=Zi(this,t).delete(t);return this.size-=e?1:0,e},$n.prototype.get=function(t){return Zi(this,t).get(t)},$n.prototype.has=function(t){return Zi(this,t).has(t)},$n.prototype.set=function(t,e){var n=Zi(this,t),r=n.size;return n.set(t,e),this.size+=n.size==r?0:1,this},jn.prototype.add=jn.prototype.push=function(t){return this.__data__.set(t,"__lodash_hash_undefined__"),this},jn.prototype.has=function(t){return this.__data__.has(t)},Yn.prototype.clear=function(){this.__data__=new Dn,this.size=0},Yn.prototype.delete=function(t){var e=this.__data__,n=e.delete(t);return this.size=e.size,n},Yn.prototype.get=function(t){return this.__data__.get(t)},Yn.prototype.has=function(t){return this.__data__.has(t)},Yn.prototype.set=function(t,e){var n=this.__data__;if(n instanceof Dn){var r=n.__data__;if(!gn||r.length<199)return r.push([t,e]),this.size=++n.size,this;n=this.__data__=new $n(r)}return n.set(t,e),this.size=n.size,this};var er=ki(lr),nr=ki(cr,!0);function rr(t,e){var n=!0;return er(t,(function(t,r,i){return n=!!e(t,r,i)})),n}function ir(t,e,n){for(var r=-1,i=t.length;++r0&&n(a)?e>1?sr(a,e-1,n,r,i):pe(i,a):r||(i[i.length]=a)}return i}var ar=xi(),ur=xi(!0);function lr(t,e){return t&&ar(t,e,wa)}function cr(t,e){return t&&ur(t,e,wa)}function hr(t,e){return le(e,(function(e){return zs(t[e])}))}function fr(t,e){for(var n=0,r=(e=ui(e,t)).length;null!=t&&ne}function vr(t,e){return null!=t&&xt.call(t,e)}function mr(t,e){return null!=t&&e in gt(t)}function yr(t,e,n){for(var i=n?he:ce,o=t[0].length,s=t.length,a=s,u=r(s),l=1/0,c=[];a--;){var h=t[a];a&&e&&(h=fe(h,Be(e))),l=un(h.length,l),u[a]=!n&&(e||o>=120&&h.length>=120)?new jn(a&&h):void 0}h=t[0];var f=-1,p=u[0];t:for(;++f=a)return u;var l=n[r];return u*("desc"==l?-1:1)}}return t.index-e.index}(t,e,n)}))}function Ir(t,e,n){for(var r=-1,i=e.length,o={};++r-1;)a!==t&&Gt.call(a,u,1),Gt.call(t,u,1);return t}function $r(t,e){for(var n=t?e.length:0,r=n-1;n--;){var i=e[n];if(n==r||i!==o){var o=i;ao(i)?Gt.call(t,i,1):ti(t,i)}}return t}function jr(t,e){return t+tn(hn()*(e-t+1))}function Yr(t,e){var n="";if(!t||e<1||e>9007199254740991)return n;do{e%2&&(n+=t),(e=tn(e/2))&&(t+=t)}while(e);return n}function Xr(t,e){return ko(vo(t,e,qa),t+"")}function Nr(t){return Nn(Ba(t))}function zr(t,e){var n=Ba(t);return Co(n,Qn(e,0,n.length))}function Rr(t,e,n,r){if(!Us(t))return t;for(var i=-1,o=(e=ui(e,t)).length,s=o-1,a=t;null!=a&&++io?0:o+e),(n=n>o?o:n)<0&&(n+=o),o=e>n?0:n-e>>>0,e>>>=0;for(var s=r(o);++i>>1,s=t[o];null!==s&&!Zs(s)&&(n?s<=e:s=200){var l=e?null:Yi(t);if(l)return He(l);s=!1,i=Me,u=new jn}else u=e?[]:a;t:for(;++r=r?t:Wr(t,e,n)}var hi=Qe||function(t){return Wt.clearTimeout(t)};function fi(t,e){if(e)return t.slice();var n=t.length,r=zt?zt(n):new t.constructor(n);return t.copy(r),r}function pi(t){var e=new t.constructor(t.byteLength);return new Dt(e).set(new Dt(t)),e}function gi(t,e){var n=e?pi(t.buffer):t.buffer;return new t.constructor(n,t.byteOffset,t.length)}function di(t,e){if(t!==e){var n=void 0!==t,r=null===t,i=t==t,o=Zs(t),s=void 0!==e,a=null===e,u=e==e,l=Zs(e);if(!a&&!l&&!o&&t>e||o&&s&&u&&!a&&!l||r&&s&&u||!n&&u||!i)return 1;if(!r&&!o&&!l&&t1?n[i-1]:void 0,s=i>2?n[2]:void 0;for(o=t.length>3&&"function"==typeof o?(i--,o):void 0,s&&uo(n[0],n[1],s)&&(o=i<3?void 0:o,i=1),e=gt(e);++r-1?i[o?e[s]:s]:void 0}}function Li(t){return Fi((function(e){var n=e.length,r=n,o=Mn.prototype.thru;for(t&&e.reverse();r--;){var s=e[r];if("function"!=typeof s)throw new mt(i);if(o&&!a&&"wrapper"==Ki(s))var a=new Mn([],!0)}for(r=a?r:n;++r1&&_.reverse(),h&&la))return!1;var l=o.get(t),c=o.get(e);if(l&&c)return l==e&&c==t;var h=-1,f=!0,p=2&n?new jn:void 0;for(o.set(t,e),o.set(e,t);++h-1&&t%1==0&&t1?"& ":"")+e[r],e=e.join(n>2?", ":" "),t.replace(K,"{\n/* [wrapped with "+e+"] */\n")}(r,function(t,e){return se(s,(function(n){var r="_."+n[0];e&n[1]&&!ce(t,r)&&t.push(r)})),t.sort()}(function(t){var e=t.match(Q);return e?e[1].split(J):[]}(r),n)))}function Po(t){var e=0,n=0;return function(){var r=ln(),i=16-(r-n);if(n=r,i>0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}function Co(t,e){var n=-1,r=t.length,i=r-1;for(e=void 0===e?r:e;++n1?t[e-1]:void 0;return n="function"==typeof n?(t.pop(),n):void 0,Ko(t,n)}));function ns(t){var e=An(t);return e.__chain__=!0,e}function rs(t,e){return e(t)}var is=Fi((function(t){var e=t.length,n=e?t[0]:0,r=this.__wrapped__,i=function(e){return Kn(e,t)};return!(e>1||this.__actions__.length)&&r instanceof En&&ao(n)?((r=r.slice(n,+n+(e?1:0))).__actions__.push({func:rs,args:[i],thisArg:void 0}),new Mn(r,this.__chain__).thru((function(t){return e&&!t.length&&t.push(void 0),t}))):this.thru(i)}));var os=bi((function(t,e,n){xt.call(t,n)?++t[n]:Gn(t,n,1)}));var ss=Si(Eo),as=Si(Io);function us(t,e){return(Is(t)?se:er)(t,Ji(e,3))}function ls(t,e){return(Is(t)?ae:nr)(t,Ji(e,3))}var cs=bi((function(t,e,n){xt.call(t,n)?t[n].push(e):Gn(t,n,[e])}));var hs=Xr((function(t,e,n){var i=-1,o="function"==typeof e,s=$s(t)?r(t.length):[];return er(t,(function(t){s[++i]=o?ie(e,t,n):_r(t,e,n)})),s})),fs=bi((function(t,e,n){Gn(t,n,e)}));function ps(t,e){return(Is(t)?fe:Lr)(t,Ji(e,3))}var gs=bi((function(t,e,n){t[n?0:1].push(e)}),(function(){return[[],[]]}));var ds=Xr((function(t,e){if(null==t)return[];var n=e.length;return n>1&&uo(t,e[0],e[1])?e=[]:n>2&&uo(e[0],e[1],e[2])&&(e=[e[0]]),Er(t,sr(e,1),[])})),vs=Je||function(){return Wt.Date.now()};function ms(t,e,n){return e=n?void 0:e,Ni(t,128,void 0,void 0,void 0,void 0,e=t&&null==e?t.length:e)}function ys(t,e){var n;if("function"!=typeof e)throw new mt(i);return t=ia(t),function(){return--t>0&&(n=e.apply(this,arguments)),t<=1&&(e=void 0),n}}var _s=Xr((function(t,e,n){var r=1;if(n.length){var i=Re(n,Qi(_s));r|=32}return Ni(t,r,e,n,i)})),bs=Xr((function(t,e,n){var r=3;if(n.length){var i=Re(n,Qi(bs));r|=32}return Ni(e,r,t,n,i)}));function ws(t,e,n){var r,o,s,a,u,l,c=0,h=!1,f=!1,p=!0;if("function"!=typeof t)throw new mt(i);function g(e){var n=r,i=o;return r=o=void 0,c=e,a=t.apply(i,n)}function d(t){return c=t,u=wo(m,e),h?g(t):a}function v(t){var n=t-l;return void 0===l||n>=e||n<0||f&&t-c>=s}function m(){var t=vs();if(v(t))return y(t);u=wo(m,function(t){var n=e-(t-l);return f?un(n,s-(t-c)):n}(t))}function y(t){return u=void 0,p&&r?g(t):(r=o=void 0,a)}function _(){var t=vs(),n=v(t);if(r=arguments,o=this,l=t,n){if(void 0===u)return d(l);if(f)return hi(u),u=wo(m,e),g(l)}return void 0===u&&(u=wo(m,e)),a}return e=sa(e)||0,Us(n)&&(h=!!n.leading,s=(f="maxWait"in n)?an(sa(n.maxWait)||0,e):s,p="trailing"in n?!!n.trailing:p),_.cancel=function(){void 0!==u&&hi(u),c=0,r=l=o=u=void 0},_.flush=function(){return void 0===u?a:y(vs())},_}var ks=Xr((function(t,e){return Vn(t,1,e)})),xs=Xr((function(t,e,n){return Vn(t,sa(e)||0,n)}));function Ps(t,e){if("function"!=typeof t||null!=e&&"function"!=typeof e)throw new mt(i);var n=function(){var r=arguments,i=e?e.apply(this,r):r[0],o=n.cache;if(o.has(i))return o.get(i);var s=t.apply(this,r);return n.cache=o.set(i,s)||o,s};return n.cache=new(Ps.Cache||$n),n}function Cs(t){if("function"!=typeof t)throw new mt(i);return function(){var e=arguments;switch(e.length){case 0:return!t.call(this);case 1:return!t.call(this,e[0]);case 2:return!t.call(this,e[0],e[1]);case 3:return!t.call(this,e[0],e[1],e[2])}return!t.apply(this,e)}}Ps.Cache=$n;var Ts=li((function(t,e){var n=(e=1==e.length&&Is(e[0])?fe(e[0],Be(Ji())):fe(sr(e,1),Be(Ji()))).length;return Xr((function(r){for(var i=-1,o=un(r.length,n);++i=e})),Es=br(function(){return arguments}())?br:function(t){return Fs(t)&&xt.call(t,"callee")&&!qt.call(t,"callee")},Is=r.isArray,Ds=Zt?Be(Zt):function(t){return Fs(t)&&gr(t)==k};function $s(t){return null!=t&&Hs(t.length)&&!zs(t)}function js(t){return Fs(t)&&$s(t)}var Ys=nn||su,Xs=Vt?Be(Vt):function(t){return Fs(t)&&gr(t)==c};function Ns(t){if(!Fs(t))return!1;var e=gr(t);return e==h||"[object DOMException]"==e||"string"==typeof t.message&&"string"==typeof t.name&&!Gs(t)}function zs(t){if(!Us(t))return!1;var e=gr(t);return e==f||e==p||"[object AsyncFunction]"==e||"[object Proxy]"==e}function Rs(t){return"number"==typeof t&&t==ia(t)}function Hs(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=9007199254740991}function Us(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}function Fs(t){return null!=t&&"object"==typeof t}var Ws=te?Be(te):function(t){return Fs(t)&&ro(t)==g};function qs(t){return"number"==typeof t||Fs(t)&&gr(t)==d}function Gs(t){if(!Fs(t)||gr(t)!=v)return!1;var e=Ut(t);if(null===e)return!0;var n=xt.call(e,"constructor")&&e.constructor;return"function"==typeof n&&n instanceof n&&kt.call(n)==St}var Ks=ee?Be(ee):function(t){return Fs(t)&&gr(t)==m};var Qs=ne?Be(ne):function(t){return Fs(t)&&ro(t)==y};function Js(t){return"string"==typeof t||!Is(t)&&Fs(t)&&gr(t)==_}function Zs(t){return"symbol"==typeof t||Fs(t)&&gr(t)==b}var Vs=re?Be(re):function(t){return Fs(t)&&Hs(t.length)&&!!Xt[gr(t)]};var ta=Di(Sr),ea=Di((function(t,e){return t<=e}));function na(t){if(!t)return[];if($s(t))return Js(t)?We(t):yi(t);if(Jt&&t[Jt])return function(t){for(var e,n=[];!(e=t.next()).done;)n.push(e.value);return n}(t[Jt]());var e=ro(t);return(e==g?Ne:e==y?He:Ba)(t)}function ra(t){return t?(t=sa(t))===1/0||t===-1/0?17976931348623157e292*(t<0?-1:1):t==t?t:0:0===t?t:0}function ia(t){var e=ra(t),n=e%1;return e==e?n?e-n:e:0}function oa(t){return t?Qn(ia(t),0,4294967295):0}function sa(t){if("number"==typeof t)return t;if(Zs(t))return NaN;if(Us(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=Us(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=Ae(t);var n=it.test(t);return n||st.test(t)?Ht(t.slice(2),n?2:8):rt.test(t)?NaN:+t}function aa(t){return _i(t,ka(t))}function ua(t){return null==t?"":Zr(t)}var la=wi((function(t,e){if(fo(e)||$s(e))_i(e,wa(e),t);else for(var n in e)xt.call(e,n)&&Un(t,n,e[n])})),ca=wi((function(t,e){_i(e,ka(e),t)})),ha=wi((function(t,e,n,r){_i(e,ka(e),t,r)})),fa=wi((function(t,e,n,r){_i(e,wa(e),t,r)})),pa=Fi(Kn);var ga=Xr((function(t,e){t=gt(t);var n=-1,r=e.length,i=r>2?e[2]:void 0;for(i&&uo(e[0],e[1],i)&&(r=1);++n1),e})),_i(t,qi(t),n),r&&(n=Jn(n,7,Hi));for(var i=e.length;i--;)ti(n,e[i]);return n}));var Ta=Fi((function(t,e){return null==t?{}:function(t,e){return Ir(t,e,(function(e,n){return ma(t,n)}))}(t,e)}));function Sa(t,e){if(null==t)return{};var n=fe(qi(t),(function(t){return[t]}));return e=Ji(e),Ir(t,n,(function(t,n){return e(t,n[0])}))}var La=Xi(wa),Aa=Xi(ka);function Ba(t){return null==t?[]:Oe(t,wa(t))}var Oa=Ci((function(t,e,n){return e=e.toLowerCase(),t+(n?Ma(e):e)}));function Ma(t){return Na(ua(t).toLowerCase())}function Ea(t){return(t=ua(t))&&t.replace(ut,$e).replace(Mt,"")}var Ia=Ci((function(t,e,n){return t+(n?"-":"")+e.toLowerCase()})),Da=Ci((function(t,e,n){return t+(n?" ":"")+e.toLowerCase()})),$a=Pi("toLowerCase");var ja=Ci((function(t,e,n){return t+(n?"_":"")+e.toLowerCase()}));var Ya=Ci((function(t,e,n){return t+(n?" ":"")+Na(e)}));var Xa=Ci((function(t,e,n){return t+(n?" ":"")+e.toUpperCase()})),Na=Pi("toUpperCase");function za(t,e,n){return t=ua(t),void 0===(e=n?void 0:e)?function(t){return $t.test(t)}(t)?function(t){return t.match(It)||[]}(t):function(t){return t.match(Z)||[]}(t):t.match(e)||[]}var Ra=Xr((function(t,e){try{return ie(t,void 0,e)}catch(t){return Ns(t)?t:new ht(t)}})),Ha=Fi((function(t,e){return se(e,(function(e){e=So(e),Gn(t,e,_s(t[e],t))})),t}));function Ua(t){return function(){return t}}var Fa=Li(),Wa=Li(!0);function qa(t){return t}function Ga(t){return Pr("function"==typeof t?t:Jn(t,1))}var Ka=Xr((function(t,e){return function(n){return _r(n,t,e)}})),Qa=Xr((function(t,e){return function(n){return _r(t,n,e)}}));function Ja(t,e,n){var r=wa(e),i=hr(e,r);null!=n||Us(e)&&(i.length||!r.length)||(n=e,e=t,t=this,i=hr(e,wa(e)));var o=!(Us(n)&&"chain"in n&&!n.chain),s=zs(t);return se(i,(function(n){var r=e[n];t[n]=r,s&&(t.prototype[n]=function(){var e=this.__chain__;if(o||e){var n=t(this.__wrapped__),i=n.__actions__=yi(this.__actions__);return i.push({func:r,args:arguments,thisArg:t}),n.__chain__=e,n}return r.apply(t,pe([this.value()],arguments))})})),t}function Za(){}var Va=Mi(fe),tu=Mi(ue),eu=Mi(ve);function nu(t){return lo(t)?Pe(So(t)):function(t){return function(e){return fr(e,t)}}(t)}var ru=Ii(),iu=Ii(!0);function ou(){return[]}function su(){return!1}var au=Oi((function(t,e){return t+e}),0),uu=ji("ceil"),lu=Oi((function(t,e){return t/e}),1),cu=ji("floor");var hu,fu=Oi((function(t,e){return t*e}),1),pu=ji("round"),gu=Oi((function(t,e){return t-e}),0);return An.after=function(t,e){if("function"!=typeof e)throw new mt(i);return t=ia(t),function(){if(--t<1)return e.apply(this,arguments)}},An.ary=ms,An.assign=la,An.assignIn=ca,An.assignInWith=ha,An.assignWith=fa,An.at=pa,An.before=ys,An.bind=_s,An.bindAll=Ha,An.bindKey=bs,An.castArray=function(){if(!arguments.length)return[];var t=arguments[0];return Is(t)?t:[t]},An.chain=ns,An.chunk=function(t,e,n){e=(n?uo(t,e,n):void 0===e)?1:an(ia(e),0);var i=null==t?0:t.length;if(!i||e<1)return[];for(var o=0,s=0,a=r(Ve(i/e));oi?0:i+n),(r=void 0===r||r>i?i:ia(r))<0&&(r+=i),r=n>r?0:oa(r);n>>0)?(t=ua(t))&&("string"==typeof e||null!=e&&!Ks(e))&&!(e=Zr(e))&&Xe(t)?ci(We(t),0,n):t.split(e,n):[]},An.spread=function(t,e){if("function"!=typeof t)throw new mt(i);return e=null==e?0:an(ia(e),0),Xr((function(n){var r=n[e],i=ci(n,0,e);return r&&pe(i,r),ie(t,this,i)}))},An.tail=function(t){var e=null==t?0:t.length;return e?Wr(t,1,e):[]},An.take=function(t,e,n){return t&&t.length?Wr(t,0,(e=n||void 0===e?1:ia(e))<0?0:e):[]},An.takeRight=function(t,e,n){var r=null==t?0:t.length;return r?Wr(t,(e=r-(e=n||void 0===e?1:ia(e)))<0?0:e,r):[]},An.takeRightWhile=function(t,e){return t&&t.length?ni(t,Ji(e,3),!1,!0):[]},An.takeWhile=function(t,e){return t&&t.length?ni(t,Ji(e,3)):[]},An.tap=function(t,e){return e(t),t},An.throttle=function(t,e,n){var r=!0,o=!0;if("function"!=typeof t)throw new mt(i);return Us(n)&&(r="leading"in n?!!n.leading:r,o="trailing"in n?!!n.trailing:o),ws(t,e,{leading:r,maxWait:e,trailing:o})},An.thru=rs,An.toArray=na,An.toPairs=La,An.toPairsIn=Aa,An.toPath=function(t){return Is(t)?fe(t,So):Zs(t)?[t]:yi(To(ua(t)))},An.toPlainObject=aa,An.transform=function(t,e,n){var r=Is(t),i=r||Ys(t)||Vs(t);if(e=Ji(e,4),null==n){var o=t&&t.constructor;n=i?r?new o:[]:Us(t)&&zs(o)?Bn(Ut(t)):{}}return(i?se:lr)(t,(function(t,r,i){return e(n,t,r,i)})),n},An.unary=function(t){return ms(t,1)},An.union=Fo,An.unionBy=Wo,An.unionWith=qo,An.uniq=function(t){return t&&t.length?Vr(t):[]},An.uniqBy=function(t,e){return t&&t.length?Vr(t,Ji(e,2)):[]},An.uniqWith=function(t,e){return e="function"==typeof e?e:void 0,t&&t.length?Vr(t,void 0,e):[]},An.unset=function(t,e){return null==t||ti(t,e)},An.unzip=Go,An.unzipWith=Ko,An.update=function(t,e,n){return null==t?t:ei(t,e,ai(n))},An.updateWith=function(t,e,n,r){return r="function"==typeof r?r:void 0,null==t?t:ei(t,e,ai(n),r)},An.values=Ba,An.valuesIn=function(t){return null==t?[]:Oe(t,ka(t))},An.without=Qo,An.words=za,An.wrap=function(t,e){return Ss(ai(e),t)},An.xor=Jo,An.xorBy=Zo,An.xorWith=Vo,An.zip=ts,An.zipObject=function(t,e){return oi(t||[],e||[],Un)},An.zipObjectDeep=function(t,e){return oi(t||[],e||[],Rr)},An.zipWith=es,An.entries=La,An.entriesIn=Aa,An.extend=ca,An.extendWith=ha,Ja(An,An),An.add=au,An.attempt=Ra,An.camelCase=Oa,An.capitalize=Ma,An.ceil=uu,An.clamp=function(t,e,n){return void 0===n&&(n=e,e=void 0),void 0!==n&&(n=(n=sa(n))==n?n:0),void 0!==e&&(e=(e=sa(e))==e?e:0),Qn(sa(t),e,n)},An.clone=function(t){return Jn(t,4)},An.cloneDeep=function(t){return Jn(t,5)},An.cloneDeepWith=function(t,e){return Jn(t,5,e="function"==typeof e?e:void 0)},An.cloneWith=function(t,e){return Jn(t,4,e="function"==typeof e?e:void 0)},An.conformsTo=function(t,e){return null==e||Zn(t,e,wa(e))},An.deburr=Ea,An.defaultTo=function(t,e){return null==t||t!=t?e:t},An.divide=lu,An.endsWith=function(t,e,n){t=ua(t),e=Zr(e);var r=t.length,i=n=void 0===n?r:Qn(ia(n),0,r);return(n-=e.length)>=0&&t.slice(n,i)==e},An.eq=Bs,An.escape=function(t){return(t=ua(t))&&Y.test(t)?t.replace($,je):t},An.escapeRegExp=function(t){return(t=ua(t))&&W.test(t)?t.replace(F,"\\$&"):t},An.every=function(t,e,n){var r=Is(t)?ue:rr;return n&&uo(t,e,n)&&(e=void 0),r(t,Ji(e,3))},An.find=ss,An.findIndex=Eo,An.findKey=function(t,e){return ye(t,Ji(e,3),lr)},An.findLast=as,An.findLastIndex=Io,An.findLastKey=function(t,e){return ye(t,Ji(e,3),cr)},An.floor=cu,An.forEach=us,An.forEachRight=ls,An.forIn=function(t,e){return null==t?t:ar(t,Ji(e,3),ka)},An.forInRight=function(t,e){return null==t?t:ur(t,Ji(e,3),ka)},An.forOwn=function(t,e){return t&&lr(t,Ji(e,3))},An.forOwnRight=function(t,e){return t&&cr(t,Ji(e,3))},An.get=va,An.gt=Os,An.gte=Ms,An.has=function(t,e){return null!=t&&io(t,e,vr)},An.hasIn=ma,An.head=$o,An.identity=qa,An.includes=function(t,e,n,r){t=$s(t)?t:Ba(t),n=n&&!r?ia(n):0;var i=t.length;return n<0&&(n=an(i+n,0)),Js(t)?n<=i&&t.indexOf(e,n)>-1:!!i&&be(t,e,n)>-1},An.indexOf=function(t,e,n){var r=null==t?0:t.length;if(!r)return-1;var i=null==n?0:ia(n);return i<0&&(i=an(r+i,0)),be(t,e,i)},An.inRange=function(t,e,n){return e=ra(e),void 0===n?(n=e,e=0):n=ra(n),function(t,e,n){return t>=un(e,n)&&t=-9007199254740991&&t<=9007199254740991},An.isSet=Qs,An.isString=Js,An.isSymbol=Zs,An.isTypedArray=Vs,An.isUndefined=function(t){return void 0===t},An.isWeakMap=function(t){return Fs(t)&&ro(t)==w},An.isWeakSet=function(t){return Fs(t)&&"[object WeakSet]"==gr(t)},An.join=function(t,e){return null==t?"":on.call(t,e)},An.kebabCase=Ia,An.last=No,An.lastIndexOf=function(t,e,n){var r=null==t?0:t.length;if(!r)return-1;var i=r;return void 0!==n&&(i=(i=ia(n))<0?an(r+i,0):un(i,r-1)),e==e?function(t,e,n){for(var r=n+1;r--;)if(t[r]===e)return r;return r}(t,e,i):_e(t,ke,i,!0)},An.lowerCase=Da,An.lowerFirst=$a,An.lt=ta,An.lte=ea,An.max=function(t){return t&&t.length?ir(t,qa,dr):void 0},An.maxBy=function(t,e){return t&&t.length?ir(t,Ji(e,2),dr):void 0},An.mean=function(t){return xe(t,qa)},An.meanBy=function(t,e){return xe(t,Ji(e,2))},An.min=function(t){return t&&t.length?ir(t,qa,Sr):void 0},An.minBy=function(t,e){return t&&t.length?ir(t,Ji(e,2),Sr):void 0},An.stubArray=ou,An.stubFalse=su,An.stubObject=function(){return{}},An.stubString=function(){return""},An.stubTrue=function(){return!0},An.multiply=fu,An.nth=function(t,e){return t&&t.length?Mr(t,ia(e)):void 0},An.noConflict=function(){return Wt._===this&&(Wt._=Lt),this},An.noop=Za,An.now=vs,An.pad=function(t,e,n){t=ua(t);var r=(e=ia(e))?Fe(t):0;if(!e||r>=e)return t;var i=(e-r)/2;return Ei(tn(i),n)+t+Ei(Ve(i),n)},An.padEnd=function(t,e,n){t=ua(t);var r=(e=ia(e))?Fe(t):0;return e&&re){var r=t;t=e,e=r}if(n||t%1||e%1){var i=hn();return un(t+i*(e-t+Rt("1e-"+((i+"").length-1))),e)}return jr(t,e)},An.reduce=function(t,e,n){var r=Is(t)?ge:Te,i=arguments.length<3;return r(t,Ji(e,4),n,i,er)},An.reduceRight=function(t,e,n){var r=Is(t)?de:Te,i=arguments.length<3;return r(t,Ji(e,4),n,i,nr)},An.repeat=function(t,e,n){return e=(n?uo(t,e,n):void 0===e)?1:ia(e),Yr(ua(t),e)},An.replace=function(){var t=arguments,e=ua(t[0]);return t.length<3?e:e.replace(t[1],t[2])},An.result=function(t,e,n){var r=-1,i=(e=ui(e,t)).length;for(i||(i=1,t=void 0);++r9007199254740991)return[];var n=4294967295,r=un(t,4294967295);t-=4294967295;for(var i=Le(r,e=Ji(e));++n=o)return t;var a=n-Fe(r);if(a<1)return r;var u=s?ci(s,0,a).join(""):t.slice(0,a);if(void 0===i)return u+r;if(s&&(a+=u.length-a),Ks(i)){if(t.slice(a).search(i)){var l,c=u;for(i.global||(i=dt(i.source,ua(nt.exec(i))+"g")),i.lastIndex=0;l=i.exec(c);)var h=l.index;u=u.slice(0,void 0===h?a:h)}}else if(t.indexOf(Zr(i),a)!=a){var f=u.lastIndexOf(i);f>-1&&(u=u.slice(0,f))}return u+r},An.unescape=function(t){return(t=ua(t))&&j.test(t)?t.replace(D,Ge):t},An.uniqueId=function(t){var e=++Pt;return ua(t)+e},An.upperCase=Xa,An.upperFirst=Na,An.each=us,An.eachRight=ls,An.first=$o,Ja(An,(hu={},lr(An,(function(t,e){xt.call(An.prototype,e)||(hu[e]=t)})),hu),{chain:!1}),An.VERSION="4.17.21",se(["bind","bindKey","curry","curryRight","partial","partialRight"],(function(t){An[t].placeholder=An})),se(["drop","take"],(function(t,e){En.prototype[t]=function(n){n=void 0===n?1:an(ia(n),0);var r=this.__filtered__&&!e?new En(this):this.clone();return r.__filtered__?r.__takeCount__=un(n,r.__takeCount__):r.__views__.push({size:un(n,4294967295),type:t+(r.__dir__<0?"Right":"")}),r},En.prototype[t+"Right"]=function(e){return this.reverse()[t](e).reverse()}})),se(["filter","map","takeWhile"],(function(t,e){var n=e+1,r=1==n||3==n;En.prototype[t]=function(t){var e=this.clone();return e.__iteratees__.push({iteratee:Ji(t,3),type:n}),e.__filtered__=e.__filtered__||r,e}})),se(["head","last"],(function(t,e){var n="take"+(e?"Right":"");En.prototype[t]=function(){return this[n](1).value()[0]}})),se(["initial","tail"],(function(t,e){var n="drop"+(e?"":"Right");En.prototype[t]=function(){return this.__filtered__?new En(this):this[n](1)}})),En.prototype.compact=function(){return this.filter(qa)},En.prototype.find=function(t){return this.filter(t).head()},En.prototype.findLast=function(t){return this.reverse().find(t)},En.prototype.invokeMap=Xr((function(t,e){return"function"==typeof t?new En(this):this.map((function(n){return _r(n,t,e)}))})),En.prototype.reject=function(t){return this.filter(Cs(Ji(t)))},En.prototype.slice=function(t,e){t=ia(t);var n=this;return n.__filtered__&&(t>0||e<0)?new En(n):(t<0?n=n.takeRight(-t):t&&(n=n.drop(t)),void 0!==e&&(n=(e=ia(e))<0?n.dropRight(-e):n.take(e-t)),n)},En.prototype.takeRightWhile=function(t){return this.reverse().takeWhile(t).reverse()},En.prototype.toArray=function(){return this.take(4294967295)},lr(En.prototype,(function(t,e){var n=/^(?:filter|find|map|reject)|While$/.test(e),r=/^(?:head|last)$/.test(e),i=An[r?"take"+("last"==e?"Right":""):e],o=r||/^find/.test(e);i&&(An.prototype[e]=function(){var e=this.__wrapped__,s=r?[1]:arguments,a=e instanceof En,u=s[0],l=a||Is(e),c=function(t){var e=i.apply(An,pe([t],s));return r&&h?e[0]:e};l&&n&&"function"==typeof u&&1!=u.length&&(a=l=!1);var h=this.__chain__,f=!!this.__actions__.length,p=o&&!h,g=a&&!f;if(!o&&l){e=g?e:new En(this);var d=t.apply(e,s);return d.__actions__.push({func:rs,args:[c],thisArg:void 0}),new Mn(d,h)}return p&&g?t.apply(this,s):(d=this.thru(c),p?r?d.value()[0]:d.value():d)})})),se(["pop","push","shift","sort","splice","unshift"],(function(t){var e=yt[t],n=/^(?:push|sort|unshift)$/.test(t)?"tap":"thru",r=/^(?:pop|shift)$/.test(t);An.prototype[t]=function(){var t=arguments;if(r&&!this.__chain__){var i=this.value();return e.apply(Is(i)?i:[],t)}return this[n]((function(n){return e.apply(Is(n)?n:[],t)}))}})),lr(En.prototype,(function(t,e){var n=An[e];if(n){var r=n.name+"";xt.call(bn,r)||(bn[r]=[]),bn[r].push({name:e,func:n})}})),bn[Ai(void 0,2).name]=[{name:"wrapper",func:void 0}],En.prototype.clone=function(){var t=new En(this.__wrapped__);return t.__actions__=yi(this.__actions__),t.__dir__=this.__dir__,t.__filtered__=this.__filtered__,t.__iteratees__=yi(this.__iteratees__),t.__takeCount__=this.__takeCount__,t.__views__=yi(this.__views__),t},En.prototype.reverse=function(){if(this.__filtered__){var t=new En(this);t.__dir__=-1,t.__filtered__=!0}else(t=this.clone()).__dir__*=-1;return t},En.prototype.value=function(){var t=this.__wrapped__.value(),e=this.__dir__,n=Is(t),r=e<0,i=n?t.length:0,o=function(t,e,n){var r=-1,i=n.length;for(;++r=this.__values__.length;return{done:t,value:t?void 0:this.__values__[this.__index__++]}},An.prototype.plant=function(t){for(var e,n=this;n instanceof On;){var r=Ao(n);r.__index__=0,r.__values__=void 0,e?i.__wrapped__=r:e=r;var i=r;n=n.__wrapped__}return i.__wrapped__=t,e},An.prototype.reverse=function(){var t=this.__wrapped__;if(t instanceof En){var e=t;return this.__actions__.length&&(e=new En(this)),(e=e.reverse()).__actions__.push({func:rs,args:[Uo],thisArg:void 0}),new Mn(e,this.__chain__)}return this.thru(Uo)},An.prototype.toJSON=An.prototype.valueOf=An.prototype.value=function(){return ri(this.__wrapped__,this.__actions__)},An.prototype.first=An.prototype.head,Jt&&(An.prototype[Jt]=function(){return this}),An}();Wt._=Ke,void 0===(r=function(){return Ke}.call(e,n,e,t))||(t.exports=r)}).call(this)}).call(this,n(50)(t))},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e){t.exports=function(t){return null==t}},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},function(t,e,n){},,function(t,e,n){"use strict";n.r(e);var r=n(11),i={name:"SidebarGroup",props:["item","open","collapsable","depth"],components:{DropdownTransition:n(291).a},beforeCreate(){this.$options.components.SidebarLinks=n(290).default},methods:{isActive:r.f}},o=(n(329),n(4)),s=Object(o.a)(i,(function(){var t=this,e=t._self._c;return e("section",{staticClass:"sidebar-group",class:[{collapsable:t.collapsable,"is-sub-group":0!==t.depth},"depth-"+t.depth]},[t.item.path?e("router-link",{staticClass:"sidebar-heading clickable",class:{open:t.open,active:t.isActive(t.$route,t.item.path)},attrs:{to:t.item.path},nativeOn:{click:function(e){return t.$emit("toggle")}}},[e("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?e("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]):e("p",{staticClass:"sidebar-heading",class:{open:t.open},on:{click:function(e){return t.$emit("toggle")}}},[e("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?e("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]),t._v(" "),e("DropdownTransition",[t.open||!t.collapsable?e("SidebarLinks",{staticClass:"sidebar-group-items",attrs:{items:t.item.children,"sidebar-depth":t.item.sidebarDepth,"initial-open-group-index":t.item.initialOpenGroupIndex,depth:t.depth+1}}):t._e()],1)],1)}),[],!1,null,null,null).exports;function a(t,e,n,r){return t("router-link",{props:{to:e,activeClass:"",exactActiveClass:""},class:{active:r,"sidebar-link":!0}},n)}function u(t,e,n,i,o,s=1){return!e||s>o?null:t("ul",{class:"sidebar-sub-headers"},e.map(e=>{const l=Object(r.f)(i,n+"#"+e.slug);return t("li",{class:"sidebar-sub-header level"+e.level},[a(t,n+"#"+e.slug,e.title,l),u(t,e.children,n,i,o,s+1)])}))}var l={functional:!0,props:["item","sidebarDepth"],render(t,{parent:{$page:e,$site:n,$route:i,$themeConfig:o,$themeLocaleConfig:s},props:{item:l,sidebarDepth:c}}){const h=Object(r.f)(i,l.path),f="auto"===l.type?h||l.children.some(t=>Object(r.f)(i,l.basePath+"#"+t.slug)):h,p="external"===l.type?function(t,e,n){return t("a",{attrs:{href:e,target:"_blank",rel:"noopener noreferrer"},class:{"sidebar-link":!0}},[n,t("OutboundLink")])}(t,l.path,l.title||l.path):a(t,l.path,l.title||l.path,f),g=[e.frontmatter.sidebarDepth,c,s.sidebarDepth,o.sidebarDepth,1].find(t=>void 0!==t),d=s.displayAllHeaders||o.displayAllHeaders;if("auto"===l.type)return[p,u(t,l.children,l.basePath,i,g)];if((f||d)&&l.headers&&!r.e.test(l.path)){return[p,u(t,Object(r.d)(l.headers),l.path,i,g)]}return p}};n(330);function c(t,e){return"group"===e.type&&e.children.some(e=>"group"===e.type?c(t,e):"page"===e.type&&Object(r.f)(t,e.path))}var h={name:"SidebarLinks",components:{SidebarGroup:s,SidebarLink:Object(o.a)(l,void 0,void 0,!1,null,null,null).exports},props:["items","depth","sidebarDepth","initialOpenGroupIndex"],data(){return{openGroupIndex:this.initialOpenGroupIndex||0}},created(){this.refreshIndex()},watch:{$route(){this.refreshIndex()}},methods:{refreshIndex(){const t=function(t,e){for(let n=0;n-1&&(this.openGroupIndex=t)},toggleGroup(t){this.openGroupIndex=t===this.openGroupIndex?-1:t},isActive(t){return Object(r.f)(this.$route,t.regularPath)}}},f=Object(o.a)(h,(function(){var t=this,e=t._self._c;return t.items.length?e("ul",{staticClass:"sidebar-links"},t._l(t.items,(function(n,r){return e("li",{key:r},["group"===n.type?e("SidebarGroup",{attrs:{item:n,open:r===t.openGroupIndex,collapsable:n.collapsable||n.collapsible,depth:t.depth},on:{toggle:function(e){return t.toggleGroup(r)}}}):e("SidebarLink",{attrs:{sidebarDepth:t.sidebarDepth,item:n}})],1)})),0):t._e()}),[],!1,null,null,null);e.default=f.exports},function(t,e,n){"use strict";var r={name:"DropdownTransition",methods:{setHeight(t){t.style.height=t.scrollHeight+"px"},unsetHeight(t){t.style.height=""}}},i=(n(315),n(4)),o=Object(i.a)(r,(function(){return(0,this._self._c)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.a=o.exports},,function(t,e,n){"use strict";n(257)},function(t,e,n){"use strict";n(258)},function(t,e,n){"use strict";n(259)},function(t,e,n){"use strict";n(260)},function(t,e,n){"use strict";n(261)},function(t,e,n){"use strict";n(262)},function(t,e,n){"use strict";n(263)},function(t,e,n){"use strict";n(264)},function(t,e,n){"use strict";var r=n(5),i=n(2),o=n(302),s=URLSearchParams.prototype,a=i(s.forEach);r&&!("size"in s)&&o(s,"size",{get:function(){var t=0;return a(this,(function(){t++})),t},configurable:!0,enumerable:!0})},function(t,e,n){var r=n(101),i=n(13);t.exports=function(t,e,n){return n.get&&r(n.get,e,{getter:!0}),n.set&&r(n.set,e,{setter:!0}),i.f(t,e,n)}},function(t,e,n){"use strict";var r=n(18),i=n(304).findLastIndex,o=n(307);r({target:"Array",proto:!0},{findLastIndex:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}}),o("findLastIndex")},function(t,e,n){var r=n(305),i=n(48),o=n(33),s=n(34),a=function(t){var e=1==t;return function(n,a,u){for(var l,c=o(n),h=i(c),f=r(a,u),p=s(h);p-- >0;)if(f(l=h[p],p,c))switch(t){case 0:return l;case 1:return p}return e?-1:void 0}};t.exports={findLast:a(0),findLastIndex:a(1)}},function(t,e,n){var r=n(306),i=n(32),o=n(29),s=r(r.bind);t.exports=function(t,e){return i(t),void 0===e?t:o?s(t,e):function(){return t.apply(e,arguments)}}},function(t,e,n){var r=n(19),i=n(2);t.exports=function(t){if("Function"===r(t))return i(t)}},function(t,e,n){var r=n(20),i=n(308),o=n(13).f,s=r("unscopables"),a=Array.prototype;null==a[s]&&o(a,s,{configurable:!0,value:i(null)}),t.exports=function(t){a[s][t]=!0}},function(t,e,n){var r,i=n(28),o=n(309),s=n(98),a=n(49),u=n(311),l=n(99),c=n(102),h=c("IE_PROTO"),f=function(){},p=function(t){return"
+