------

[ AD ] Port Monitor ( Try to use a Best WebSite Monitoring Tool )

------
100가지 법칙 - 자연을 움직이는 현상, 인간 세상을 움직이는 이치,

도전과 응전의 법칙/도도새의 법칙/질투의 법칙/피보나치의 수열/파동 이론/세렌디피티의 법칙/몰락의 법칙/마지노선의 법칙/1:99의 법칙/파레토의 법칙, 80:20/긴 꼬리의 법칙, 롱테일/후광 효과/마이너리티 인플런스 현상/프레임의 법칙/베버의 법칙/이륙-추진-균형의 법칙/활주로 이론/퀀텀 점프 이론/1만 시간의 법칙/관성의 법칙, 뉴턴의 운동 방정식

경로의존의 법칙/X이론, 당근과 채찍/종속의 효과/하인리히 법칙/대마불사의 법칙/쉘의 시나리오 기법/깨진 유리창의 법칙/주역과 변화의 법칙/마라톤의 법칙/단테의 법칙/최소량의 법칙/최소량 곱셈의 법칙/적자생존의 법칙/붉은 여왕의 법칙/밴드왜건 효과/멘델의 유전 법칙/확률과 대수의 법칙/동종교배 퇴화의 법칙/멈 효과

노 리스크 노 리턴의 법칙/시그모이드 곡선 이론/레몬 시장의 법칙/오쿤의 계수/펭귄 효과/다윗의 법칙/역발상의 법칙/광속 불변의 법칙/치킨 게임의 법칙/오컴의 면도날 법칙/1:81의 법칙/단순함의 법칙/나비 효과/수확체감의 법칙/수확체증의 법칙/마태 효과와 메칼프의 법칙/파킨슨의 법칙/피터의 원리/란체스터의 법칙

위위구조의 법칙/피그말리온 효과/위약 효과, 플라세보/에너지 보존의 법칙/열역학 제2법칙과 엔트로피의 법칙/빅뱅의 법칙/불확정성의 법칙/근접성의 효과와 유사성의 법칙/넘버원의 법칙/원근의 법칙/정보의 제시순서 효과/알래스카와 72의 법칙/2/3의 법칙, 1/3의 법칙 그리고 72의 법칙/피타고라스의 역설/250명의 법칙/수면자 효과/토사구팽의 법칙/폰지 게임과 로의 법칙/뷰자데와 신사고 이론

기동력과 승수 효과/벤치의 법칙과 청바지 법칙/메디치 효과/링겔만 효과/70:20:10의 법칙/스마일 커브의 법칙/선택의 법칙과 죄수의 딜레마/환골탈태의 법칙/머피의 법칙과 샐리의 법칙/우물의 법칙/차도살인의 계책/희생양의 법칙/음양의 법칙과 디지털/샤를의 법칙과 렌츠의 법칙/정반합의 법칙


피보나치의 수열 Fibonacci sequence
피보나치는 복리 계산법을 토끼의 증식과정에 비유하고 있다. 갓 태어난 1쌍의 토끼가 있다. 이 1쌍의 토끼는 두 달이면 성년이 되어 그때부터 매월 1쌍의 새끼를 낳는다고 가정하자. 새로 태어난 토끼들도 두 달이 지나 성년이 되면 매월 1쌍의 새끼를 낳는다고 가정한다. 그렇게 될 경우 ‘1년 후 토끼는 모두 몇 마리로 늘어날까?’ 하는 문제이다. 새로 태어난 새끼도 두 달이 지나면 새끼를 치기 시작하기 때문에 이것은 전형적인 복리계산이 된다. 이 문제를 산술적으로 풀려면 머리가 복잡해진다. 이것을 간단한 수열로 풀이한 내용이 피보나치의 수열이다.

피보나치의 풀이로 들어가 보자. 갓 태어난 1쌍의 토끼는 처음 두 달 동안은 새끼를 낳지 않으므로 1쌍 그대로이다. 따라서 수열의 처음 두 자리는 1, 즉 1 그대로이다. 3번째 달이 되면 어미가 새끼 1쌍을 낳을 것이므로 토끼는 모두 2쌍으로 늘어난다. 4번째 달에는 어미가 다시 1쌍의 새끼를 낳을 것이므로 토끼는 모두 3쌍이 된다. 5번째 달이 되면 어미가 1쌍, 처음 태어난 새끼도 두 달이 지났으므로 다시 1쌍의 새끼를 낳을 것이므로 새로 태어난 토끼는 모두 2쌍, 토끼는 모두 5쌍으로 늘어난다. 그리하여 1년 후에는 모두 144마리로 늘어난다. 이를 순서대로 배열하면 다음과 같이 표기된다. 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144…… 이것이 피보나치의 수열이다. 여기서 피보나치는 아주 간략한 계산법을 제시하고 있다. 이웃한 두 숫자를 합하면 다음에 나타날 숫자가 나타난다는 것이다.

1과 1의 합이 2가 되고, 1과 2의 합이 3이 된다. 마찬가지로 2와 3의 합이 5로 나타나며, 3과 5의 합이 8로 나타난다. 이것을 나무로 그려보면 훨씬 이해가 빠를 것이다. 이제 막 심은 나무는 2년 후부터 매년 하나씩의 새로운 가지가 나온다. 새로 나온 가지도 2년 후부터는 다시 새로운 가지를 뻗는다고 하면 실제의 나무 모습과 너무도 흡사하다. 전체 가지의 수는 1, 2년까지는 원 줄기 하나뿐이지만 3년 차에는 원 줄기에서 새로운 가지 하나가 뻗어나 둘, 4년차에는 원 줄기에서 다시 하나의 가지가 뻗어 셋, 그 이후에는 원 줄기와 처음 줄기에서 하나씩의 가지가 뻗어 다섯이 된다. 피보나치의 수열이 가장 잘 나타나는 곳은 식물의 잎차례이다. 돌려나기, 어긋나기, 마주나기 등에서 ?차례는 2/5, 3/8, 5/13 등으로 이 수열을 따르고 있다. 2/5란 잎차례가 두 번 돌아가는 동안에 5개의 잎사귀가 난다는 의미이다.

자연계가 피보나치의 수열을 따르는 이유는 무엇일까? 나무라면 원 줄기에서 뻗어나는 가지와 잎들이 모두 햇살을 고르게 받을 수 있는 최적의 조건이 이 수열이라고 한다. 식물의 80% 정도가 이 수열을 따르는 것으로 알려지고 있다. 피보나치의 수열이 특별한 의미를 갖는 것은 자연의 신비를 닮았다는 점에서이다. 그럴 수밖에 없는 것이, 이 수열의 개념 자체가 동물의 번식과정을 모방한 것이기 때문이다. 동물계의 특성은 어미가 새끼를 낳고, 태어난 새끼도 일정 기간이 지나면 어른이 되어 다시 생식활동에 동참하는 것이다.

그래서 피보나치의 수열은 동물의 증식과정 뿐만 아니라 식물의 성장과정도 그대로 반영하고 있다. 자연의 증식과정은 기본적으로 복리를 지향하고 있다. 해바라기나 솔방울 씨앗의 배열, 파인애플의 껍질, 국화나 데이지 꽃잎의 배열 등이 피보나치의 수열과 같은 모습으로 나타난다. 해바라기 씨앗이라면 시계방향과 그 반대방향으로 나선형을 이루고 있는데, 어느 곳으로나 피보나치의 수열과 이웃한 숫자로 나타난다.

어느 쪽의 나선형에서 21이 나타나면 반대편으로는 34, 아니면 34 혹은 55와 같은 연속된 피보나치의 수열을 형성하고 있다. 이것이 한정된 공간에서 가장 많은 씨앗을 품을 수 있는 조건이라는 것이다. 소라껍데기의 구조, 소용돌이치는 물이나 회오리바람, 태풍, 나아가서는 은하계의 중심부도 피보나치의 수열을 이루고 있다. 자연 뿐 아니라 사회 현상도 복리의 구조를 닮아 있다. 유행이나 인터넷의 보급 속도가 전형적이다. 하나의 흐름이 나타나면 ‘그런가?’ 하면서 무언가 대책을 세워야겠다고 막연하게 생각하다가 얼마 후에는 ‘이거 장난 아니네!’가 된다는 이야기이다. 기업이라면 경영에 영향을 미칠 새로운 하나의 흐름이 나타났다면 그 흐름을 복리로 계산해보라. 그리하여 그 흐름에 편승할 수 있는 방법을 찾아야 한다.

파레토의 법칙, 80:20 Pareto's law
파레토의 법칙은 일반인들에게 80:20의 법칙으로 더 잘 알려져 있다. 경제학자, 사회학자인 파레토는 토리노 대학에서 수학과 물리학을 공부했으며, 피렌체 대학에서는 철학과 정치학을 공부했다. 파레토의 관심은 소득 분배에 있었다.

그는 자신의 수학적 재능을 무기로 소득의 분배는 역사적으로, 사회적으로 일정한 틀이 있다는 것을 입증하려 하였다. 그것을 한 줄로 요약하자면 “사회 전체 부의 80%를 20%의 소수가 차지한다.”는 80:20의 법칙이다. 사람들은 파레토를 80:20의 법칙을 발견한 사람 정도로 기억하고 있지만 그는 이런 불평등을 해소하기 위해서는 경제학이 아니라 사회학적으로 접근해야 한다며 후생경제학의 초석을 놓은 위대한 경제학자로 이해하는 것이 옳다.

80:20의 법칙이 좀 더 설득력이 있는 것은 자연의 모습과 흡사하다는 점에 있다.

공기 중의 질소와 산소의 비율이 78:22로 이에 근접하며 지구상의 바다와 육지의 비율, 육지 중에서 산과 평지의 비율이 이에 흡사하다.
 
정사각형에 내접하는 원을 그릴 경우 사각형의 넓이에서 원의 넓이를 뺀 값은 원 넓이와 78:22의 비율을 이룬다.

사실 80:20의 법칙은 78:22의 변형이라고 보아야 할 것이다. 파레토는 농민들의 소득실태를 이 법칙에 비유해보았더니 풍년이 들었을 때 전체적인 생활수준은 향상되었지만 하위 20%는 여전히 생활이 어려웠으며 아무리 흉년이 들어도 상위 20%는 곳간을 가득 채우고 있더라는 것이다. 여기서 파레토의 법칙은 사회 현상을 설명하는 중요한 이론으로 자리를 잡기 시작했다.

이를 기업에 적용하자면 10가지 상품을 시장에 팔고 있는 기업이 10억의 매출을 올렸다면 모든 상품이 고르게 1억씩 매출을 올린 게 아니라, 2개의 대표 상품이 전체 매출의 80%를 차지하는 반면 나머지 8개 상품은 20%에 그친다는 것이다.

은행 예금의 80%는 20%의 사람들이 예치한 돈이며, 백화점은 불과 20%의 핵심 고객들이 전체 매출의 80%에 기여한다는 의미이다. 이 법칙이 마케팅에 적용되기 시작하면서 기업, 특히 유통업체들은 핵심이 되는 상위 20%의 고객을 집중적으로 관리하기 시작하였다. 곧 VIP 마케팅이다.

후광 효과 halo effect
우리는 어떤 사람에게서 한 가지 좋은 점이 있으면 다른 점도 모두 좋게 보려는 경향이 있다. 이렇듯 첫 인상이 좋으면 성격도, 집안도, 학벌도 모두 좋을 것이라고 믿으려는 사람들의 성향을 후광 효과라고 부른다. 만약 새로운 약을 팔려고 하는 경우, 제약회사의 세일즈맨이 약효를 설명하는 것보다 그 분야의 전문가인 대학교수나 약학자의 의견을 소개하는 자료를 보이면 효과는 배가 된다. 일종의 ‘권위자의 보증’이라고 할 수 있는데, 미끼로 사용하는 권위자의 능력, 지명도, 직업, 인품, 상대와의 관계 등에 따라 후광 효과가 발휘되슴 위력은 큰 차이가 난다.

스페인 왕 카를로스에게 세계 일주를 계획한 마젤란이 협력을 요청할 때 이러한 후광 효과를 사용해 성공을 거두었다. 당시에는 콜럼버스의 성공 이래 많은 사기꾼이나 허풍쟁이들이 스폰서를 구하기 위해 궁정을 방문하고 있었다. 그래서 마젤란은 자신이 그런 부류와는 다르다는 것을 보여주기 위해 왕을 알현하는 자리에 유명한 지리학자 루이 파레이로를 대동했다. 또한 파레이로는 지구의를 앞에 놓고 마젤란 항해의 정당성을 역설했는데, 결국 이것이 힘이 되어 스페인 왕 카를로스를 설득시켜 항해 허가를 얻어냈다. 그러나 마젤란 항해 이후, 그의 세계 지리에 대한 지식이 상당히 잘못된 것이었고 그가 계산한 경도와 위도도 많은 오차가 있다는 것이 판명되었다. 이렇게 보면 의견의 내용이 어떠한가가 중요한 역할을 했다고 보기는 힘들다. 즉 왕으로서는 ‘전문가의 의견’이라는 사실 하나만으로 신뢰할 수 있었던 것이다.

“세계적으로 최고의 권위를 인정받고 있는 ○○○ 과학지에 따르면…….” “사장님도 이 기획에는 반대하지 않는 것 같은데…….” 이처럼 우리들은 후광 효과를 모든 생활에서 거의 무의식적으로 끈질기게 사용하고 있다. 대부분의 사람들은 조금이라도 권위의 냄새가 풍기면 자신의 주장이나 소신을 밝히기보다는 재빨리 이에 영합하려는 자세를 취한다. 아주 자연스럽게 설득이 이루어진다. 세일즈맨이 회원 권유 수단의 하나로 자주 쓰는 말이 있다. “유명한 연예인 ○○○도 이 상품을 사용합니다.” 무단으로 자신의 이름이 팔린 연예인은 불쾌하겠지만 실제와 다른 정보를 흘리는 경우도 많이 있다. 악용해서는 결코 안 되겠지만 권위자나 전문가의 의견을 원용하는 것으로 자신의 의견에 대한 설득력을 높이는 것은 대인관계를 유리하게 이끄는 유효한 수단이 된다.

하인리히 법칙 Heinrich's Law
제비가 낮게 날면 곧 비가 온다. 어린 시절에 어른들로부터 자주 듣는 말이었다. 제비가 낮게 나는 것은 먹이가 되는 잠자리가 낮게 날기 때문이다. 잠자리가 낮게 나는 것은 공중에 습기가 많아 날개가 젖기 때문이다. 잠자리는 잘 보이지 않지만 제비가 낮게 나는 것은 쉽게 목격할 수 있기 때문에 제비가 낮게 날면 비가 온다고 한 것이다.

이처럼 세상 모든 것은 징후를 앞세우며 다가온다. 그리고는 흔적을 남기고 사라진다. 사회적인 현상들도 마찬가지다. 교통사고가 잦은 곳에서는 머지않아 대형사고가 기다리고 있는 것으로 보면 맞다. 몇 가지 잠재적인 징후들이 앞서거니 뒤서거니 하면서 우연처럼 겹쳐질 때, 큰 사건으로 이어진다. 한 번의 대형사고가 일어나기 전에 여러 번의 작은 사고가 지나가고 잠재적인 사고는 더 많이 지나간다는 것이다.

이것을 처음 통계적인 법칙으로 정립한 사람은 하버드 윌리엄 하인리히였다.

미 해군장교 출신의 하인리히는 보험회사에서 보험 감독관으로 산업재해 관련 일을 하고 있었다. 크고 작은 각종 산업 재해, 그 사고들 사이에는 어떤 상관관계 같은 것이 있을 거라는 느낌을 받게 되면서 본격적인 연구에 착수했다. 그는 보험사에 접수된 5만 건의 사건, 사고에 대한 자료를 분석하여 이들의 통계적인 상관관계를 밝혀냈다. 그에 의하면 한 번의 대형사고, 이를테면 산업재해로 사망사고가 발생했다면 그 이전에 동일한 원인으로 인한 부상이 29건 발생했으며, 부상으로까지 이어지지는 않았지만 사고가 날 뻔한 경우가 300건 정도가 있었더라는 것이다.

1929년에 발표된 이 논문은 하인리히 법칙으로 명명되었다.

이를 사회적인 사건, 사고에 적용하면 강력 범죄사건 하나가 발생했다면 동일 수법의 경범죄가 29회, 범죄로 이어지지는 않았지만 범죄의 시도가 300건 정도 있었다는 의미로 해석된다. 하인리히는 또 사고로 인한 재해비용에 대해서도 통계적으로 의미 있는 가설을 내놓았다. 하나의 사고로 인해 재해가 발생할 경우 그 비용은 직접비용이 하나라면 간접비용은 넷이라는 것이다. 따라서 재해비용 전체를 계산하려면 직접적인 손해비용에다 곱하기 다섯을 하라는 것이다. 눈에 보이는 직접적인 손해보다는 보이지 않는 간접적인 손실이 더 크다는 이야기이다.

그후 하인리히 법칙은 타이와 피어슨에 의해 훨씬 더 정교하게 분석되었다. 그들이 영국 보험회사의 사건, 사고 100만 건을 분석하여 발표한 결과를 보면 사망사고 1건 뒤에는 중경상 3건, 응급처치 50건, 물손사고 80건, 사고가 날 뻔한 사례가 400건으로 집계되었다. 이 법칙들은 자연 현상이나 사회 현상 모두에 공통적으로 적용되는 법칙으로, 어떤 사회적인 큰 사건이 일어날 때도 특정 사건이 어느날 갑자기 나타나는 것이 아니라 이를 암시하는 작은 사건들이 잇따라 지나간다는 것이다.

깨진 유리창의 법칙 Broken Window Theory
하인리히 법칙을 역으로 적용하자면 대형 교통사고를 예방하는 가장 좋은 방법은 조그만 교통질서부터 단속쿇는 것이다. 더러운 곳을 없애면 파리나 모기가 서식하지 못하는 것과 같은 이치이다. 범죄도 마찬가지이다. 사회의 어두운 곳을 없애면 범죄가 설 자리도 점점 더 좁아지리라는 추론이 가능해진다.

최근 필리핀에 있는 한 교도소가 세계적인 화제를 낳고 있다. 필리핀의 세부 지역에 있는 이 교도소는 새로운 소장이 부임하면서 체력 단련 시간을 이용하여 춤을 가르치기 시작했다. 다른 교도소들이 규율을 정해놓고 생활을 엄격하게 통제하는 것에 반해 여기서는 죄수들에게 춤을 가르쳤다. 이들이 춤을 출 때 틀어주는 노래도 다양하다. 초기에는 마이클 잭슨의 노래를 많이 틀었으나 최근에는 우리나라 가수인 원더걸스의 노바디가 인기라고 한다. 그렇게 하자 이들의 표정이 훨씬 더 밝아지더라고 한다. 교도소 생활을 그렇게 바꾸었더니 오히려 통제도 훨씬 쉬워졌고 출소자들의 재범률도 다른 곳에 비해 현저히 낮아졌다. 범죄가 태어나고 자라는 어두운 환경을 밝게 바꾼 결과라는 것이다.

미국 스탠포드 대학의 심리학과 필립 짐바르도 교수는 흥미 있는 실험을 했다. 낙후된 골목에 상태가 비슷한 자동차 두 대를 세우고서 한 대에는 보닛을 조금 열어둔 상태로, 다른 한 대에는 보닛을 열고 유리창도 조금 깨진 상태로 방치했다. 그리고 1주일 후에 보았더니 유리창이 깨진 자동차는 배터리와 타이어를 빼가고 사방에 낙서를 하고 돌을 던져 거의 고철상태가 되어 있더라는 것이다. 유리창이 조금 깨진 것 밖에 차이가 없는데도 그런 차이가 났다. 여기서 ‘깨진 유리창의 법칙’이 나온다. 일단 금이 간 유리창은 전체가 쉽게 망가진다는 이야기이다.

1980년대 뉴욕 경찰 당국은 뉴욕 지하철 범죄로 골머리를 앓고 있었다. 밤이면 뉴욕 지하철을 탄다는 것 자체가 공포였다. 경찰국장은 깨진 유리창의 법칙에서 힌트를 얻어 범죄의 심리적 온상이 되는 것은 지하철 낙서라고 생각하고 그때부터 낙서를 없애기로 마음먹었다. 그러나 지워도 지워도 다시 낙서를 하는 바람에 지하철 낙서를 완전히 뿌리 뽑기까지는 5년이 걸렸다. 마침내 1989년이 되어 지하철의 모든 낙서를 지웠다. 낙서를 지우기 시작하면서 서서히 줄어들던 범죄율이 1994년에는 절반 가까이 줄어들었고, 중범죄의 경우는 75%가 줄어드는 기적이 일어났다.

시그모이드 곡선 Sigmoid Curve
수학 이론 중에 시그모이드 곡선이라는 게 있다. ‘생명주기 곡선’을 가리키는 용어이다. 기업이든 국가든 상품이든 시작과 끝이 있는 모든 것은 도입기, 성장기, 성숙기를 거쳐 소멸해간다. 성장곡선은 도입기에는 느린 속도로 움직이지만 일단 성장 궤도에 진입하면 빠른 속도로 움직이다가 성숙 단계에 이르면 다시 속도가 느려진다. 여기서 새로운 동력을 얻지 못하면 소멸한다. 이것을 느린 시작 단계(slow beginning), 빠른 가속 단계(speed acceleration)라고 부르며, 이후의 느린 성장 단계를 고지 단계(plateau)로 부른다. 고지 단계는 성숙기의 다른 표현이다.

시간을 X축, 성장률을 Y축이라고 하면 성장곡선은 영문 대문자 ‘S’를 오른쪽으로 비스듬하게 눕혀 놓은 형태를 보인다. 그래서 생명주기 곡선을 S곡선이라 부르기도 한다. 생명주기 곡선에는 두 번의 위험이 도사리고 있다. 하나는 도입기와 성장기 사이에 있는 특이점(singular point)이며 다른 하나는 성장기와 성숙기 사이에 있는 변곡점(Inflection Point)이다. 특이점이란 스위치를 on-off 할 때처럼 사느냐, 죽느냐의 갈림길로 상품에 따라 차이가 있으나 대략 보급률 10%대를 가리킨다. 그 시점이 사느냐 죽느냐의 갈림길이라는 것이다. 처음 10%의 사람들이 수용할 때까지는 뜸을 들이지만 일단 특이점을 통과하면 빠르게 수용된다. 변곡점이란 성장기와 성숙기 사이에 존재하는 점으로 성장세가 둔화되기 시작하는 시점을 가리킨다. 이 시기에 새로운 추진력을 얻지 못하면 소멸되고 만다. 이 두 번의 위기를 넘기는 기업이 우량 기업이다.

새로운 기술이나 상품이 나타나 초기 수용자들에 의해 수용되는 도입기에는 성장 속도가 아주 느리다. 그래서 처음 10%의 소비자 계층에 보급될 때까지의 시간이 10%에서 90%의 소비자들에게 수용될 때까지의 시간과 거의 일치한다. 외국어 공부도 좋은 사례일 것이다. 처음 외국어를 배우기 시작하는 단계에서는 진도가 아주 느리지만 일단 그 단계를 지나면 성장 궤도에 올라 외국어의 70~80%를 이해하기까지 빠른 속도로 진행된다. 그러나 거기서부터는 다시 느려진다. 외국인들이 던지는 농담을 완전히 알아듣기까지는 다시 많은 시간이 걸린다는 것이다. 그러나 S자 성장 곡선이 한 줄기의 큰 획으로 그려지는 것은 아니다. 큰 S자는 다시 여러 개의 작은 S자로 분할되어 이어진다. 이때가 기업으로서는 고비를 맞는 시기이다.

'People in' 카테고리의 다른 글

페이스북 vs 미국 연방 의회 / 연방정부 친구 만들기  (0) 2010.12.20
칭찬의 역효과  (0) 2010.12.15
경로 의존 법칙  (0) 2010.11.16
가사 : 언제나 ~ 허각  (0) 2010.11.12
커피 프림의 원료인 팜유는  (0) 2010.10.25
업데이트 update 시에 조인 join 활용 // 확장 update문장

--- 1. 테이블 삭제 / 생성
drop table cus
drop table ordercall

create table cus(
cus_no varchar(2) not null,
cus_tot_order int
)
create table ordercall (
ordercall_no varchar(5) not null,
cus_no varchar(2)
)
--- 2. 인덱스 생성
--alter table cus add constraint cus_pk primary key(cus_no)
create index cus_idx1 on cus(cus_no)

--alter table ordercall add constraint ordercall_pk primary key(ordercall_no)
create index ordercall_idx1 on ordercall(ordercall_no)

---- 3. 테스트 데이타  입력
insert into cus values( '01' , 0 )
insert into cus values( '02' , 0 )
insert into cus values( '03' , 0 )

insert into ordercall values ( 'A0001', '01' )
insert into ordercall values ( 'A0002', '02' )
insert into ordercall values ( 'A0003', '03' )
insert into ordercall values ( 'A0004', '01' )
insert into ordercall values ( 'A0005', '02' )
insert into ordercall values ( 'A0006', '03' )
insert into ordercall values ( 'A0007', '01' )
insert into ordercall values ( 'A0008', '02' )

---- 4. 테스트 데이타 조회
select * from cus
select * from ordercall

-- 5. 업데이트 update 시에 조인 join 활용 // 확장 update문장

-- ORACLE
-- update cus a
-- set ( cus_tot ) = ( select COUNT(*) from ordercall b where b.cus_no = a.cus_no )

-- SQL 2000

update a
set a.cus_tot_order = b.cus_tot_order 
from cus a, ( select b.cus_no , COUNT(*) as cus_tot_order from ordercall b group by b.cus_no ) b
where a.cus_no = b.cus_no

select * from cus
select * from ordercall



MS SQL 데이타 베이스 쿼리문 문법 예제

http://www.functionx.com/sqlserver/index.htm


연합뉴스 11월 17일 뉴스

위 기사 내용을 정리 하면...


      출고가 출고가 출고가
    용량 16gb 32gb 64gb
    wifi + 3g  79만원 89만원 99만원
2년약정 월 27500 2GB 40만원 50만원 60만원
2년약정 월 42500 4Gb 22만원 32만원 42만원
           
    wifi 64만원 75만원 87만원


.air 확장자 설치 install

개별 학습
비디오: 간단한 Flex Adobe AIR 애플리케이션 구축
자습서: 간단한 Flex Adobe AIR 애플리케이션 구축


자세한 내용 :   Flex 사용해 보기: Flex 데스크탑 애플리케이션 제작

Adobe Developer Connection에 오신 것을 환영합니다. Flex 애플리케이션 개발 방법에 대한 자세한 내용을 살펴보시려면 이 페이지에서 제공하는 리소스를 참조하십시오.

이메일에 포함되어 있는 샘플 애플리케이션을 살펴보거나 Tour de Flex의 샘플을 테스트해 보면서 Flex를 사용하여 수행할 수 있는 작업을 확인하고 비디오 및 자습서를 통해 단계별로 학습하면서 Flash Builder를 사용하여 기본 AIR 데스크탑 애플리케이션을 구축하는 방법을 배울 수 있습니다.



<<<
:: 데스크톱에서 AIR 응용 프로그램을 실행


Windows® 및 Mac OS X 버전의 AIR을 다운로드하고 설치합니다.

런타임을 업데이트하려면 사용자에게 컴퓨터에 대한 관리 권한이 필요합니다.


Windows 컴퓨터에 런타임 설치

  1. 런타임 설치 파일을 다운로드합니다.

  2. 런타임 설치 파일을 두 번 클릭합니다.

  3. 설치 윈도우에서 프롬프트에 따라 설치를 완료합니다.





Mac 컴퓨터에 런타임 설치

  1. 런타임 설치 파일을 다운로드합니다.

  2. 런타임 설치 파일을 두 번 클릭합니다.

  3. 설치 윈도우에서 프롬프트에 따라 설치를 완료합니다.

  4. 설치 프로그램에서 인증 윈도우를 표시하면 해당 Mac OS 사용자 이름과 암호를 입력합니다.

Adobe AIR 제거

런타임을 설치하면 다음 절차에 따라 제거할 수 있습니다.

Windows 컴퓨터에서 런타임 제거

  1. Windows [시작] 메뉴에서 [설정] > [제어판]을 선택합니다.

  2. [프로그램 추가/제거] 제어판을 선택합니다.

  3. "Adobe AIR"을 선택하여 런타임을 제거합니다.

  4. [변경/제거] 단추를 클릭합니다.

Mac 컴퓨터에서 런타임 제거

  • /Applications 폴더에 있는 “Adobe AIR Uninstaller”를 두 번 클릭합니다.



ms sql
문자열

특정쿼리의 결과 레코드를 하나의 문자열, 특히 CSV(Comma Separaed Value) 형태로 바꾸는 방법

USE pubs
GO

CREATE FUNCTION dbo.ConcatAuthors(@State CHAR(2))
RETURNS VARCHAR(8000)
AS
BEGIN
 DECLARE @Output VARCHAR(8000)
 SET @Output = ''

 SELECT @Output = CASE @Output 
    WHEN '' THEN au_lname 
    ELSE @Output + ', ' + au_lname 
    END
 FROM Authors
 WHERE State = @State
 ORDER BY au_lname

 RETURN @Output
END
GO


아래 링크는 태요 사이트의 저장 프로시저 관련 기초 설명 페이지입니다.

 

http://taeyo.pe.kr/lecture/10_ADO/SP01.asp

CREATE PROC[EDURE] procedure_name [;number]
    [
        {@parameter data_type} [VARYING] [= default] [OUTPUT]
    ]
    [,...n]
[WITH
    {
        RECOMPILE
        | ENCRYPTION
        | RECOMPILE, ENCRYPTION
    }
]
[FOR REPLICATION]
AS
    sql_statement [...n]


http://taeyo.pe.kr/lecture/10_ADO/SP02.asp



CREATE PROC usp_UpdatePrice_Output
    @type    char(12),
    @plus    Float,
    @MaxPrice    Float OUTPUT
AS
Begin
    Update titles SET price = price + @plus
    Where type = @type

    Select @MaxPrice = max(price) from titles Where type = @type
End



CREATE PROC usp_UpdatePrice_Return
    @type    char(12),
    @plus    Float
AS
Begin
    Declare @Check    int

    Select @Check = Max(price) from titles
    Where type = @type

    if @Check < 50
        Begin
            Update titles SET price = price + @plus
            Where type = @type

            Select @Check = 1
        End
    Else
        Select @Check = 0

    Return @Check
End

http://www.devpia.com/Maeul/Contents/Detail.aspx?BoardID=39&MAEULNO=16&no=892&page=1


-----------------------------------------------------------------
[MS-SQL][Stored Procedures][Visual C++ 6.0 예제 Program]
-----------------------------------------------------------------

----------------------------------------------------------------
[CREATE TABLE] - [iMageList]
--------------------------------
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[iMageList]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table   [dbo].[iMageList]
GO

CREATE TABLE [dbo].[iMageList]
(
             [iMageNUM] [int] IDENTITY (1, 1) NOT NULL ,
             [iMagePath] [varchar] (255) COLLATE Korean_Wansung_CI_AS NOT NULL ,
             [iMageFile] [varchar] (255) COLLATE Korean_Wansung_CI_AS NOT NULL ,
             [iMageSize] [int] NULL
) ON         [PRIMARY]
GO

ALTER TABLE  [dbo].[iMageList] WITH NOCHECK ADD
CONSTRAINT   [PK_iMageList] PRIMARY KEY  CLUSTERED
(
             [iMageNUM]
) ON         [PRIMARY]
GO

----------------------------------------------------------------


----------------------------------------------------------------
[iMageDB - iMageList] Table
+--------------------------------+
|     [iMageDB] - [DataBase]     |
+--------------------------------+
|            iMageList           |
+----------------+---------+-----+
| iMageNUM       | int     |   4 |
| iMagePath      | varchar | 255 |
| iMageFile      | varchar | 255 |
| iMageSize      | int     |   4 |
+----------------+---------+-----+
----------------------------------------------------------------


----------------------------------------------------------------
[Stored Procedures]

----------------------------------------------------------------
[PF1_1_5_iMageList_LIST]
----------------------------------------------------------------
CREATE PROCEDURE [PF1_1_5_iMageList_LIST]
                (@USER_TOP  [INT],
                 @iMageName [VARCHAR](255))

AS

SET ROWCOUNT @USER_TOP

SELECT
            [dbo].[iMageList].iMagePath,
            [dbo].[iMageList].iMageFile,
            [dbo].[iMageList].iMageSize,
            [dbo].[iMageList].iMageNUM
FROM        [dbo].[iMageList]
WHERE      ([dbo].[iMageList].iMageFile LIKE @iMageName)
ORDER BY    [dbo].[iMageList].iMageNUM DESC

GO


----------------------------------------------------------------
[PF1_1_5_iMageList_DELETE]
----------------------------------------------------------------
CREATE PROCEDURE [PF1_1_5_iMageList_DELETE]
                (@DB_ERR      [INT] OUTPUT,
                 @iMageNUM_1  [INT])

AS

SET @DB_ERR=0

SET XACT_ABORT OFF

BEGIN TRANSACTION

DELETE [iMageDB].[dbo].[iMageList]
WHERE ([iMageDB].[dbo].[iMageList].[iMageNUM] = @iMageNUM_1)

IF @@ERROR <> 0

   BEGIN
         ROLLBACK TRANSACTION
         SET @DB_ERR = 544
         RETURN
   END

COMMIT TRANSACTION
RETURN

GO


----------------------------------------------------------------
[PF1_1_5_iMageList_iNSERT]
----------------------------------------------------------------
CREATE PROCEDURE [PF1_1_5_iMageList_iNSERT]
                (@DB_ERR           [INT] OUTPUT,
                 @iMageNUM_1       [INT] OUTPUT,
                 @iMagePath_2      [VARCHAR](255),
                 @iMageFile_3      [VARCHAR](255),
                 @iMageSize_4      [INT])

AS

SET @DB_ERR=0

SET XACT_ABORT OFF

BEGIN TRANSACTION

INSERT INTO [iMageDB].[dbo].[iMageList]
           ([iMagePath],
            [iMageFile],
            [iMageSize])
VALUES
           (@iMagePath_2,
            @iMageFile_3,
            @iMageSize_4)

IF @@ERROR <> 0

   BEGIN
         ROLLBACK TRANSACTION
         SET @DB_ERR = 541

         RETURN
   END

SET @iMageNUM_1 = (SELECT MAX([dbo].[iMageList].iMageNUM) FROM [iMageDB].[dbo].[iMageList])

COMMIT TRANSACTION
RETURN

GO


----------------------------------------------------------------


----------------------------------------------------------------
[T-SQL]-[Data Insert]
----------------------------------------------------------------
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'CostumePlay_001.jpg', 34511)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'CostumePlay_002.jpg', 83316)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'CostumePlay_003.jpg', 95997)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'CostumePlay_004.jpg', 192613)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'CostumePlay_005.jpg',  33858)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'CostumePlay_006.jpg',  67318)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'CostumePlay_007.jpg', 64452)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'imgGirl_001.jpg', 224121)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'imgGirl_002.jpg',  58777)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'imgGirl_003.jpg',  33838)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'imgGirl_004.jpg', 191308)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'imgGirl_005.jpg', 467618)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'imgGirl_006.jpg', 184552)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'imgGirl_007.jpg',  78885)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'jpnGirl_001.jpg', 56778)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'jpnGirl_002.jpg', 123445)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'jpnGirl_003.jpg', 179880)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'jpnGirl_004.jpg',  98878)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'jpnGirl_005.jpg', 105567)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'jpnGirl_006.jpg', 58890)
INSERT INTO iMageList ([iMagePath], [iMageFile], [iMageSize]) VALUES ('iMageList\', 'jpnGirl_007.jpg',  71103)
----------------------------------------------------------------



//--------------------------------------------------------------
[include files] - [stdafx.h]
//------------------------------
#pragma warning(push)
#pragma warning(disable:4146)
#import "c:\Program Files\Common Files\System\ADO\msado15.dll" no_namespace rename("EOF","adoEOF")
#pragma warning(pop)
//--------------------------------------------------------------


//--------------------------------------------------------------
[ClassView] - [CADOVCApp]

BOOL CADOVCApp::InitInstance()
{
     CoInitialize(NULL); //ADO 초기화
}

int CADOVCApp::ExitInstance()
{
    CoUninitialize();   //ADO 제거

    return CWinApp::ExitInstance();
}


//--------------------------------------------------------------
[include] - [ADOVCDlg.h]


#include "ADODB.h"

class CADOVCDlg : public CDialog
{
public:
    void Execute_Message_Send(CString GetMessage);
    void iMageList_LiST_View();
    BOOL DBConnect();
    CADODB m_ADO;
    CStatusBar  m_wndStatusBar;


//--------------------------------------------------------------
[ClassView] - [CADOVCDlg]

BOOL CADOVCDlg::OnInitDialog()
{
    if(!DBConnect())
    {
        AfxMessageBox("Error DB Connect!!");
    }
}


//--------------------------------------------------------------
[ClassView] - [CADOVCDlg]

void CADOVCDlg::Execute_Message_Send(CString GetMessage)
{
    m_Message_List.AddString(GetMessage);
    m_Message_List.SetTopIndex(m_Message_List.GetCount() - 1);
}

// Stored Procedure - [MS-SQL][Microsoft Visual C++ 6.0]
BOOL CADOVCDlg::DBConnect()
{
    if(m_ADO.DBConnect("550107", "sa", "iMageDB", "SCORPION"))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

void CADOVCDlg::OnBtnDelete()
{
    CString msgString;
    long ErrorNUM = 0;
    BOOL b_GetValue = TRUE;

    m_DB_Delete_NUM = GetDlgItemInt(IDC_EDIT_DELETE, &b_GetValue, FALSE);

    msgString.Format(_T("[삭제] - [PF1_1_5_iMageList_DELETE]"));
    m_wndStatusBar.SetPaneText(0, msgString);

    msgString.Format(_T("[삭제]-[PF1_1_5_iMageList_DELETE] - [삭제번호] → [%d]"),
                     m_DB_Delete_NUM);
    Execute_Message_Send(msgString);

    msgString.Format(_T("삭제번호 : [%d]\n\n삭제 하시겠습니까?"), m_DB_Delete_NUM);
    if(AfxMessageBox(msgString, MB_YESNO) == IDYES)
    {
        m_ADO.Open_Command("PF1_1_5_iMageList_DELETE");
        m_ADO.Add_Parameters("@DB_ERR", adInteger, 4, adParamOutput, 0l);
        m_ADO.Add_Parameters("@iMageNUM_1", adInteger, 4, adParamInput, m_DB_Delete_NUM);
        ErrorNUM = m_ADO.QueryExecute("@DB_ERR");

        if(ErrorNUM == 0)
        {
            msgString.Format(_T("[삭제] → [Success]"));
            Execute_Message_Send(msgString);

            iMageList_LiST_View();
        }
        else
        {
            if (ErrorNUM == 544)
            {
                msgString.Format(_T("[iMageList][Delete ERROR] [Delete NUM] : [%d] %s"),
                                 m_DB_Delete_NUM, m_ADO.db_Error_Message);
            }
            else
            {
                msgString.Format(_T("[PF1_1_5_iMageList_DELETE][Delete ERROR] %s"),
                                 m_ADO.db_Error_Message);
            }
            Execute_Message_Send(msgString);
        }
    }
}

void CADOVCDlg::OnBtnInsert()
{
    CString msgString;
    long ErrorNUM = 0;
    BOOL b_GetValue = TRUE;

    long Get_INPUT_Error_NUM = 0;
    long Get_iMageNUM = 0;

    GetDlgItemText(IDC_EDIT_PATH, m_DB_Insert_Path);
    GetDlgItemText(IDC_EDIT_FILENAME, m_DB_Insert_FileName);
    m_DB_Insert_FileSize = GetDlgItemInt(IDC_EDIT_FILESIZE, &b_GetValue, FALSE);

    msgString.Format(_T("[저장] - [PF1_1_5_iMageList_iNSERT"));
    m_wndStatusBar.SetPaneText(0, msgString);

    msgString.Format(_T("[저장]-[PF1_1_5_iMageList_iNSERT] - [파일명] → [%s]"),
                     m_DB_Insert_FileName);
    Execute_Message_Send(msgString);

    if(!m_ADO.IsOpen_DB())
    {
        DBConnect();
    }

    m_ADO.Open_Command("PF1_1_5_iMageList_iNSERT");
    m_ADO.Add_Parameters("@DB_ERR", adInteger, 4, adParamOutput, 0l);
    m_ADO.Add_Parameters("@iMageNUM_1", adInteger, 4, adParamOutput, 0l);
    m_ADO.Add_Parameters("@ImagePath_2", adVarChar, 255, adParamInput, _variant_t(m_DB_Insert_Path));
    m_ADO.Add_Parameters("@ImageFile_3", adVarChar, 255, adParamInput, _variant_t(m_DB_Insert_FileName));
    m_ADO.Add_Parameters("@iMageSize_4", adInteger, 4, adParamInput, m_DB_Insert_FileSize);
    ErrorNUM = m_ADO.QueryExecute("@DB_ERR");

    if(ErrorNUM == 0)
    {
        msgString.Format(_T("[추가] → [Success]"));
        Execute_Message_Send(msgString);

        iMageList_LiST_View();
    }
    else
    {
        if (ErrorNUM == 541)
        {
            msgString.Format(_T("[iMageList][iNSERT ERROR] [iMageList FileName] : [%d] %s"),
                             m_DB_Insert_FileName, m_ADO.db_Error_Message);
        }
        else
        {
            msgString.Format(_T("[iMageList][iNSERT ERROR] %s"),
                             m_ADO.db_Error_Message);
        }
        Execute_Message_Send(msgString);
    }
}

void CADOVCDlg::OnBtnSearch()
{
    CString msgString;

    msgString.Format(_T("[조회] - [PF1_1_5_iMageList_LIST]"));
    m_wndStatusBar.SetPaneText(0, msgString);

    iMageList_LiST_View();
}

void CADOVCDlg::iMageList_LiST_View()
{
    CString msgString;
    CString db_Get_String;
    CString str_temp;

    int iROWCOUNT;
    int iField;

    BOOL b_GetValue = TRUE;

    GetDlgItemText(IDC_EDIT_SEARCH_FILENAME, m_DB_Search_FileName);
    m_DB_UserTOP = GetDlgItemInt(IDC_EDIT_USER_TOP, &b_GetValue, FALSE);

    if(m_DB_Search_FileName.GetLength() == 0 || !b_GetValue)
    {
        m_DB_Search_FileName = '%';
    }
    else
    {
        m_DB_Search_FileName = m_DB_Search_FileName + '%';
    }

    msgString.Format(_T("[조회][Stored_Procedure - %s] - [검색문자 : %s]"),
                     _T("PF1_1_5_iMageList_LIST"), m_DB_Search_FileName);
    Execute_Message_Send(msgString);

    if(!m_ADO.IsOpen_DB())
    {
        DBConnect();
    }

    m_ADO.Open_Command("PF1_1_5_iMageList_LIST");
    m_ADO.Add_Parameters("@USER_TOP", adInteger, 4, adParamInput, m_DB_UserTOP);
    m_ADO.Add_Parameters("@iMageName", adVarChar, 255, adParamInput, _variant_t(m_DB_Search_FileName));

    if(m_ADO.RowReader())
    {
        _bstr_t bt;

        iROWCOUNT = m_ADO.GetRecCount();
        if(iROWCOUNT <= 0) return;
        iField = m_ADO.GetFieldCount();

        msgString.Format(_T("Record : [%d]"), iROWCOUNT);
        m_wndStatusBar.SetPaneText(1, msgString);
        msgString.Format(_T("Field : [%d]"), iField);
        m_wndStatusBar.SetPaneText(2, msgString);

        m_ADO.GetRS(_variant_t((short)0), bt);

        m_DB_Search_List.DeleteAllItems();
        for(int iROW = 0; iROW < iROWCOUNT; iROW++)
        {
            str_temp.Format(_T("%d"), (iROW + 1));
            m_DB_Search_List.InsertItem(iROW, str_temp);
            for(int jCOL = 0; jCOL < iField; jCOL++)
            {
                m_ADO.GetRS(_variant_t((short)jCOL), bt);
                db_Get_String.Format(_T(("%s"), (LPCTSTR)bt);

                m_DB_Search_List.SetItemText(iROW, (jCOL + 1), db_Get_String);
            }

            m_ADO.Next();
        }
        m_ADO.Close_RS();
    }
    else
    {
        msgString.Format(_T("Table ROW Read Error [%s]"),
                         m_ADO.db_Error_Message);
        Execute_Message_Send(msgString);
    }
}



//--------------------------------------------------------------
[New Class...]


[Class type] : [Generic Class] | [Name] : [CADODB]

#include "ADODB.h"

class CADODB
{
private:
    _RecordsetPtr  m_RS;
    _CommandPtr    m_CMD;
    _ConnectionPtr m_CONN;

public:
             CADODB();
    virtual ~CADODB();

    CString  db_Error_Message;

    BOOL     DBConnect(char* pWD, char* pID, char* pDataBase, char* pConnectIP);
    BOOL     IsOpen_DB();
    BOOL     IsOpen_RS();
    void     Close_RS();

    BOOL     IsEOF();
    BOOL     Next();
    BOOL     First();

    int      GetRecCount();
    int      GetFieldCount();

    void     GetRS(_variant_t x, _bstr_t& ret);
    void     GetRS(_variant_t x, _variant_t& ret);
    void     GetRS(_variant_t x, float& ret);
    void     GetRS(_variant_t x, long& ret);
    void     GetRS(_variant_t x, double& ret);

    void     Open_Command(char* StoredProcedureString);
    void     Add_Parameters(_bstr_t _ParameterName,
                             DataTypeEnum _SqlDbType,
                             int _Size,
                             ParameterDirectionEnum _Direction,
                            _variant_t _User_Value);

    BOOL     RowReader();
    long     QueryExecute(_bstr_t _ParameterName);
};



//--------------------------------------------------------------
[ClassView] - [CADODB]

CADODB::CADODB()
{
    m_RS = NULL;
    m_CMD = NULL;
    m_CONN = NULL;
}

CADODB::~CADODB()
{
    if(m_RS != NULL)
    {
        if(IsOpen_RS())
        {
            m_RS->Close();
        }
    }

    if(m_CONN != NULL)
    {
        if(IsOpen_DB())
        {
            m_CONN->Close();
        }
    }
}

BOOL CADODB::DBConnect(char* pWD, char* pID, char* pDataBase, char* pConnectIP)
{
    CString strConnectionString;
    strConnectionString.Format(_T("Provider=SQLOLEDB.1;Password = %s;
                                   Persist Security Info=True;
                                   User ID = %s;
                                   Initial Catalog = %s;
                                   Data Source = %s"),
                                   pWD,
                                   pID,
                                   pDataBase,
                                   pConnectIP);

    m_CONN.CreateInstance("ADODB.Connection");
    m_CONN->ConnectionString = _bstr_t(strConnectionString);
    HRESULT hr = m_CONN->Open("", "", "", -1);

    if(SUCCEEDED(hr))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

BOOL CADODB::IsOpen_DB()
{
    return ((m_CONN->GetState() == adStateOpen ) ? TRUE : FALSE);
}

BOOL CADODB::IsOpen_RS()
{
    return ((m_RS->GetState() == adStateOpen ) ? TRUE : FALSE);
}

void CADODB::Close_RS()
{
    if(IsOpen_RS())
    {
        m_RS->Close();
    }
}

BOOL CADODB::IsEOF()
{
    return m_RS->adoEOF;
}

BOOL CADODB::Next()
{
    return (FAILED(m_RS->MoveNext()) ? FALSE : TRUE);
}

BOOL CADODB::First()
{
    return (FAILED(m_RS->MoveFirst()) ? FALSE : TRUE);
}

int CADODB::GetRecCount()
{
    HRESULT hr;
    ASSERT(m_RS != NULL);
    try
    {
        int count = (int)m_RS->GetRecordCount();

        if (count < 0)
        {
            hr = m_RS->MoveFirst();
            count = 0;
            while (!m_RS->adoEOF)
            {
                count++;
                m_RS->MoveNext();
            }
        }

        if (m_RS->adoEOF)
        {
            m_RS->MoveFirst();
        }

        return count;
    }
    catch (_com_error ex)
    {
        TRACE(_T("Warning: GetRecordCount ErrorMessage: %s;
                 File: %s;
                 Line: %d\n"),
                  ex.ErrorMessage(),
                  __FILE__,
                  __LINE__);
        return -1;
    }
}

int CADODB::GetFieldCount()
{
    return (int)m_RS->Fields->GetCount();
}

void CADODB::GetRS(_variant_t x, _bstr_t& ret)
{
    ret = m_RS->Fields->Item[x]->Value;
}

void CADODB::GetRS(_variant_t x, _variant_t& ret)
{
    ret = m_RS->Fields->Item[x]->Value;
}

void CADODB::GetRS(_variant_t x, float& ret)
{
    ret = m_RS->Fields->Item[x]->Value;
}

void CADODB::GetRS(_variant_t x, long& ret)
{
    ret = m_RS->Fields->Item[x]->Value;
}

void CADODB::GetRS(_variant_t x, double& ret)
{
    ret = m_RS->Fields->Item[x]->Value;
}

void CADODB::Open_Command(char* StoredProcedureString)
{
    m_CMD.CreateInstance("ADODB.Command");
    m_CMD->CommandText = StoredProcedureString;
    m_CMD->CommandType = adCmdStoredProc;
}

void CADODB::Add_Parameters(_bstr_t _ParameterName,
                             DataTypeEnum _SqlDbType,
                             int _Size,
                             ParameterDirectionEnum _Direction,
                            _variant_t _User_Value)
{
    _ParameterPtr AddParameter;
    AddParameter.CreateInstance("ADODB.Parameter");
    AddParameter->Name = _ParameterName;
    AddParameter->Type = _SqlDbType;
    AddParameter->Size = _Size;
    AddParameter->Direction = _Direction;
    m_CMD->Parameters->Append(AddParameter);
    m_CMD->Parameters->Item[_ParameterName]->Value = _User_Value;
}

BOOL CADODB::RowReader()
{
    try
    {
        m_CMD->ActiveConnection = m_CONN;
        m_CMD->Execute(NULL, NULL, adCmdStoredProc);

        m_RS.CreateInstance(__uuidof(Recordset));
        m_RS->PutRefSource(m_CMD);

        _variant_t vNull;
        vNull.vt = VT_ERROR;
        vNull.scode = DISP_E_PARAMNOTFOUND;
        m_RS->CursorLocation = adUseClient;
        m_RS->Open(vNull, vNull, adOpenStatic, adLockOptimistic, adCmdStoredProc);

        return true;
    }
    catch (_com_error ex)
    {
        if(m_RS != NULL)
        {
            db_Error_Message = ex.ErrorMessage();
            Close_RS();
        }
        return false;
    }
}

long CADODB::QueryExecute(_bstr_t _ParameterName)
{
    m_CMD->ActiveConnection = m_CONN;

    try
    {
        m_CMD->Execute(NULL, NULL, adCmdStoredProc);

        return long(m_CMD->Parameters->Item[_ParameterName]->Value);
    }
    catch (_com_error ex)
    {
        db_Error_Message = ex.ErrorMessage();

        return -1;
    }
}


SELECT @@IDENTITY


insert into ....

SELECT @@IDENTITY

 Insert문 실행 후 새로 삽입된 자동증가값을 얻을 때 사용

[TIP]저장 프로시저 최적화 

 

저장 프로시저는 여러가지 장점을 가지고 있습니다.
비지니스 로직을 구현하다 보면 단순한 로직으로 한번에 쿼리를 실행하여 처리할 없는 경우가 다수입니다.
이런 경우 비지니스 로직을 저장 프로시저측에서 구현하고 클라이언트(Front, Web Service, 그외 미들티어)에서는
필요한 매개변수만 서버측(SQL Server) 프로시저에 전달하여 처리 시 비지니스 로직 보안, 클라이언트 간의

효율적인 처리 루틴공유, 데이터 무결성, 이와 더불어 네트워크의 트래픽도 감소하게 됩니다.

여러번의 인라인 쿼리를 서버측에 전송하여 데이터를 주고 받는 통신 횟수를 있는 장점도 가지고 있습니다.

 

또한 최적화된 결과를 컴파일하여 실행계획(쿼리플랜) 메모리 캐시에 등록하여 동일한 SQL 실행 캐싱된
실행계획을 통해 결과를 반환하기 때문에 성능 상의 이점이 높습니다.

 

이러한 프로시저에서 최적화에 관려된 몇가지 팁을 정리해보았습니다.

 

 1) SET NOCOUNT OFF
쿼리에 대한 결과 수를 반환하지 않도록 설정합니다.
저장 프로시저 측에 안되는 쿼리를 실행시에는 크게 영향이 없겠지만
MSDN 나온 내용처럼 Transact-SQL 루프가 포함된 프로시저의 경우 SET NOCOUNT ON으로
설정하면 네트워크 트래픽이 크게 줄기 때문에 성능이 크게 향상됩니다.
결론적으로 OLE DB 통신 DONE_IN_PROC 메시지 발생이 비활성화 되기 때문에
해당 패킷이 전달되지 않으므로 부분에 대한 네트워크 트래픽이 감소 됩니다.

 

2) dbo 소유자 명시
프로시저 생성, 수정시 dbo 소유자를 명시하여 객체의 권한을 따로 검사하지 않게 합니다.
테이블 또한 다른 DB 있는 테이블 접근인 경우 아래와 같이 데이터베이스명,소유자.객체명 형식으로 지정합니다.
프로시저 내에서 다른 데이터베이스에 테이블을 지정한 경우 => [데이터베이스명].[소유자명].테이블명
프로시저가 존재하는 동일한 데이터베이스내에 테이블을 지정한 경우 => [소유자명].테이블명

 

3)접두사 sp_ 사용하지 않습니다.
저장 프로시저 호출 프로시저명이 SP_ 시작되는 경우 master 데이터베이스에서 해당 프로시저를
먼저 찾으므로 검색 여분에 대한 오버헤드가 발생할 있습니다.
동일한 저장프로시저명이 다른 데이터베이스에 있는 경우 전체이름을 지정하여 호출하지 않은 경우
master 프로시저가 호출되므로 잘못된 결과가 발생 있습니다.

 

4) 불필요한 BEGIN, END 제거
프로시서 생성 Syntax 에서는 BEGIN, END 블록 지정이 필요하지 않습니다.
코드의 간결성을 위해 불필요한 BEGIN, END 사용은 굳이 필요가 없습니다.

-- 프로시서 생성문 예제
CREATE PROC [dbo].[FSP_CAT_ProductSellingInfoBatchByCoupon_U]

AS

 SET NOCOUNT ON;

--여기서부터로직구현코드

 

5) EXECUTE 대신 sp_executesql 사용
Oracle
bind Variable, MySQL prepare 처럼 sp_executesql 를 사용하여 프로시저 내부에

Transact-SQL 실행계획을 사용할 있도록 합니다.
-- EXECUTE 사용시 DECLARE @Query VARCHAR ( 100 )
DECLARE @MemberId VARCHAR(50)

SET @MemberId = 'algorizm'

SET @Query = 'SELECT * FROM dbo.TB_PRF_Member WHERE MemberId = ' + @MemberId

EXEC ( @Query )

 

-- sp_executesql 사용시

DECLARE @Query NVARCHAR ( 100 )

SET @MemberId = N'SELECT * FROM dbo.TB_PRF_Member WHERE MemberId = @MemberId'

EXECUTE sp_executesql @Query , N'@MemberId' , @MemberId = 'algorizm'

 

6) EXISTS * 대신 1 사용
TRUE 값인지 체크하여 DROP 하면 되므로 * 통한 필요한 컬럼은 사용하지 않습니다.

보통 프로시저 내에서 해당 테이블이 있는지 검사 후 DROP 할 때 아래와 같은 예제를 많이 사용합니다.

IF EXISTS ( SELECT 1 FROM sysobjects WHERE name = 'TableName' AND type = 'U' )

DROP TABLE TableName

 

7) 커서 사용 자제
커서는 프로세싱 오버헤드가 많이 발생하므로 되도록 WHILE 문을 통한 루프 처리하는 형식으로 변경합니다.

-- 커서 사용 예제는생략

SET NOCOUNT ON

 

DECLARE @tar_table_name VARCHAR(500)

DECLARE @table_irow INT

DECLARE @table_maxrow INT

DECLARE @querytext VARCHAR(500)

DECLARE @constraint_name VARCHAR(500)

 

-- 테이블명지정

SET @tar_table_name = 'dbo.ServerUpgradeHistory'

 

DECLARE @constraint_list TABLE(

nid INT IDENTITY(1,1) NOT NULL,

constraint_name varchar(500) NOT NULL

)

 

WHILE @table_irow <= @table_maxrow

BEGIN

  -- 로직처리

  SET @table_irow = @table_irow + 1

END


http://www.sqler.com/bColumn/316463

'온라인게임' 카테고리의 다른 글

[MS-SQL][Stored Procedures][Visual C++ 6.0 예제 Program]  (0) 2010.11.16
@@identity  (0) 2010.11.16
Proactor Pattern  (0) 2010.11.15
Reactor Pattern  (0) 2010.11.15
stored procedure 저장 프로시져 확인 방법  (0) 2010.11.12

+ Recent posts